home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 November / macformat-018.iso / Utility Spectacular / Developer / macgambit-20-compiler-src-p2 / Runtime (.scm & .s) / _numbers.scm < prev    next >
Encoding:
Text File  |  1994-07-26  |  84.2 KB  |  2,622 lines  |  [TEXT/gamI]

  1. (##include "header.scm")
  2.  
  3. ;------------------------------------------------------------------------------
  4.  
  5. ; Number stuff
  6.  
  7. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  8.  
  9. ; There are 5 internal representations for numbers:
  10. ;
  11. ; fixnum, bignum, ratnum, flonum, cpxnum
  12. ;
  13. ; Fixnums and bignums form the class of exact-int.
  14. ; Fixnums, bignums and ratnums form the class of exact-real.
  15. ; Fixnums, bignums, ratnums and flonums form the class of non-cpxnum.
  16.  
  17. ; The representation has some invariants:
  18. ;
  19. ; The numerator of a ratnum is an exact-int.
  20. ; The denominator of a ratnum is a positive (>1) exact-int.
  21. ; The numerator and denominator have no common divisors.
  22. ;
  23. ; The real part of a cpxnum is a non-cpxnum.
  24. ; The imaginary part of a cpxnum is a non-cpxnum != fixnum 0
  25.  
  26. ; The following table gives the mapping of the Scheme exact numbers to their
  27. ; internal representation:
  28. ;
  29. ;    type          representation
  30. ; exact integer  = exact-int (fixnum, bignum)
  31. ; exact rational = exact-real (fixnum, bignum, ratnum)
  32. ; exact real     = exact-real (fixnum, bignum, ratnum)
  33. ; exact complex  = exact-real or cpxnum with exact-real real and imag parts
  34.  
  35. ; For inexact numbers, the representation is not quite as straightforward.
  36. ;
  37. ; There are 3 "special" classes of inexact representation:
  38. ; flonum-int : flonum with integer value
  39. ; cpxnum-real: cpxnum with imag part = flonum 0.0
  40. ; cpxnum-int : cpxnum-real with exact-int or flonum-int real part
  41. ;
  42. ; This gives to the following table for Scheme's inexact numbers:
  43. ;
  44. ;      type          representation
  45. ; inexact integer  = flonum-int or cpxnum-int
  46. ; inexact rational = flonum     or cpxnum-real
  47. ; inexact real     = flonum     or cpxnum-real
  48. ; inexact complex  = flonum     or cpxnum
  49.  
  50. (##define-macro (exact-int? x) ; x can be any object
  51.   `(or (##fixnum? ,x) (##bignum? ,x)))
  52.  
  53. (##define-macro (exact-real? x) ; x can be any object
  54.   `(or (exact-int? ,x) (##ratnum? ,x)))
  55.  
  56. (##define-macro (flonum-zero? x) ; x can be any object
  57.   `(and (##flonum? ,x) (##flonum.zero? ,x)))
  58.  
  59. (##define-macro (flonum-int? x) ; x must be a flonum
  60.   `(##flonum.= ,x (##flonum.truncate ,x)))
  61.  
  62. (##define-macro (non-cpxnum-int? x) ; x must be in fixnum/bignum/ratnum/flonum
  63.   `(if (##flonum? ,x) (flonum-int? ,x) (##not (##ratnum? ,x))))
  64.  
  65. (##define-macro (non-cpxnum-zero? x) ; x must be in fixnum/bignum/ratnum/flonum
  66.   `(if (##fixnum? ,x) (##fixnum.= ,x 0) (flonum-zero? ,x)))
  67.  
  68. (##define-macro (cpxnum-int? x) ; x must be a cpxnum
  69.   `(and (cpxnum-real? ,x)
  70.         (let ((real (cpxnum-real ,x))) (non-cpxnum-int? ,x))))
  71.  
  72. (##define-macro (cpxnum-real? x) ; x must be a cpxnum
  73.   `(let ((imag (cpxnum-imag ,x))) (flonum-zero? imag)))
  74.  
  75. (##define-macro (inexact-+2)     2.0)
  76. (##define-macro (inexact--2)    -2.0)
  77. (##define-macro (inexact-+1)     1.0)
  78. (##define-macro (inexact--1)    -1.0)
  79. (##define-macro (inexact-+1/2)   0.5)
  80. (##define-macro (inexact-0)      0.0)
  81. (##define-macro (inexact-+pi)    3.141592653589793)
  82. (##define-macro (inexact--pi)   -3.141592653589793)
  83. (##define-macro (inexact-+pi/2)  1.5707963267948966)
  84. (##define-macro (inexact--pi/2) -1.5707963267948966)
  85. (##define-macro (cpxnum-+2i)    +2i)
  86. (##define-macro (cpxnum--i)     -i)
  87. (##define-macro (cpxnum-+i)     +i)
  88.  
  89. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  90.  
  91. ; Numerical type predicates
  92.  
  93. (define (##complex? x)
  94.   (number-dispatch x #f #t #t #t #t #t))
  95.  
  96. (define (##real? x)
  97.   (number-dispatch x #f #t #t #t #t (cpxnum-real? x)))
  98.  
  99. (define (##rational? x)
  100.   (number-dispatch x #f #t #t #t #t (cpxnum-real? x)))
  101.  
  102. (define (##integer? x)
  103.   (number-dispatch x #f #t #t #f (flonum-int? x) (cpxnum-int? x)))
  104.  
  105. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  106.  
  107. ; Exactness predicates
  108.  
  109. (define (##exact? x)
  110.  
  111.   (define (error) (##trap-check-number 'exact? x))
  112.  
  113.   (number-dispatch x (error) #t #t #t #f
  114.     (and (##not (##flonum? (cpxnum-real x)))
  115.          (##not (##flonum? (cpxnum-imag x))))))
  116.  
  117. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  118.  
  119. ; Numerical comparison predicates
  120.  
  121. (define (##eqv? x y)
  122.   (number-dispatch x (##eq? x y)
  123.     (if (##fixnum? y) (##fixnum.= x y) #f)
  124.     (if (##bignum? y) (##bignum.= x y) #f)
  125.     (if (##ratnum? y) (##ratnum.= x y) #f)
  126.     (and (##complex? y) (##not (##exact? y)) (##= x y))
  127.     (and (##complex? y) (##eq? (##exact? x) (##exact? y)) (##= x y))))
  128.  
  129. (define (##= x y)
  130.  
  131.   (define (error) (##trap-check-number '= x y))
  132.  
  133.   (number-dispatch x (error)
  134.  
  135.     (number-dispatch y (error) ; x = fixnum
  136.       (##fixnum.= x y)
  137.       #f
  138.       #f
  139.       (##flonum.= (##flonum.<-fixnum x) y)
  140.       (##cpxnum.= (##cpxnum.<-non-cpxnum x) y))
  141.  
  142.     (number-dispatch y (error) ; x = bignum
  143.       #f
  144.       (##bignum.= x y)
  145.       #f
  146.       (##flonum.= (##flonum.<-bignum x) y)
  147.       (##cpxnum.= (##cpxnum.<-non-cpxnum x) y))
  148.  
  149.     (number-dispatch y (error) ; x = ratnum
  150.       #f
  151.       #f
  152.       (##ratnum.= x y)
  153.       (##ratnum.= x (##flonum.->ratnum y))
  154.       (##cpxnum.= (##cpxnum.<-non-cpxnum x) y))
  155.  
  156.     (number-dispatch y (error) ; x = flonum
  157.       (##ratnum.= (##flonum.->ratnum x) (##ratnum.<-exact-int y))
  158.       (##ratnum.= (##flonum.->ratnum x) (##ratnum.<-exact-int y))
  159.       (##ratnum.= (##flonum.->ratnum x) y)
  160.       (##flonum.= x y)
  161.       (##cpxnum.= (##cpxnum.<-non-cpxnum x) y))
  162.  
  163.     (number-dispatch y (error) ; x = cpxnum
  164.       (##cpxnum.= x (##cpxnum.<-non-cpxnum y))
  165.       (##cpxnum.= x (##cpxnum.<-non-cpxnum y))
  166.       (##cpxnum.= x (##cpxnum.<-non-cpxnum y))
  167.       (##cpxnum.= x (##cpxnum.<-non-cpxnum y))
  168.       (##cpxnum.= x y))))
  169.  
  170. (define (##< x y)
  171.  
  172.   (define (error) (##trap-check-real '< x y))
  173.  
  174.   (number-dispatch x (error)
  175.  
  176.     (number-dispatch y (error) ; x = fixnum
  177.       (##fixnum.< x y)
  178.       (bignum-positive? y)
  179.       (##ratnum.< (##ratnum.<-exact-int x) y)
  180.       (##flonum.< (##flonum.<-fixnum x) y)
  181.       (if (cpxnum-real? y) (##< x (cpxnum-real y)) (error)))
  182.  
  183.     (number-dispatch y (error) ; x = bignum
  184.       (bignum-negative? x)
  185.       (##bignum.< x y)
  186.       (##ratnum.< (##ratnum.<-exact-int x) y)
  187.       (##flonum.< (##flonum.<-bignum x) y)
  188.       (if (cpxnum-real? y) (##< x (cpxnum-real y)) (error)))
  189.  
  190.     (number-dispatch y (error) ; x = ratnum
  191.       (##ratnum.< x (##ratnum.<-exact-int y))
  192.       (##ratnum.< x (##ratnum.<-exact-int y))
  193.       (##ratnum.< x y)
  194.       (##ratnum.< x (##flonum.->ratnum y))
  195.       (if (cpxnum-real? y) (##< x (cpxnum-real y)) (error)))
  196.  
  197.     (number-dispatch y (error) ; x = flonum
  198.       (##ratnum.< (##flonum.->ratnum x) (##ratnum.<-exact-int y))
  199.       (##ratnum.< (##flonum.->ratnum x) (##ratnum.<-exact-int y))
  200.       (##ratnum.< (##flonum.->ratnum x) y)
  201.       (##flonum.< x y)
  202.       (if (cpxnum-real? y) (##< x (cpxnum-real y)) (error)))
  203.  
  204.     (if (cpxnum-real? x) ; x = cpxnum
  205.       (number-dispatch y (error)
  206.         (##< (cpxnum-real x) y)
  207.         (##< (cpxnum-real x) y)
  208.         (##< (cpxnum-real x) y)
  209.         (##< (cpxnum-real x) y)
  210.         (if (cpxnum-real? y) (##< (cpxnum-real x) (cpxnum-real y)) (error)))
  211.       (error))))
  212.  
  213. (define (##zero? x)
  214.  
  215.   (define (error) (##trap-check-number 'zero? x))
  216.  
  217.   (number-dispatch x (error) (##fixnum.= x 0) #f #f (##flonum.zero? x)
  218.     (let ((imag (cpxnum-imag x)))
  219.       (and (flonum-zero? imag)
  220.            (let ((real (cpxnum-real x)))
  221.              (non-cpxnum-zero? real))))))
  222.  
  223. (define (##positive? x)
  224.  
  225.   (define (error) (##trap-check-real 'positive? x))
  226.  
  227.   (number-dispatch x (error)
  228.     (##fixnum.positive? x)
  229.     (bignum-positive? x)
  230.     (##positive? (ratnum-numerator x))
  231.     (##flonum.positive? x)
  232.     (if (cpxnum-real? x) (##positive? (cpxnum-real x)) (error))))
  233.  
  234. (define (##negative? x)
  235.  
  236.   (define (error) (##trap-check-real 'negative? x))
  237.  
  238.   (number-dispatch x (error)
  239.     (##fixnum.negative? x)
  240.     (bignum-negative? x)
  241.     (##negative? (ratnum-numerator x))
  242.     (##flonum.negative? x)
  243.     (if (cpxnum-real? x) (##negative? (cpxnum-real x)) (error))))
  244.  
  245. (define (##odd? x)
  246.  
  247.   (define (error) (##trap-check-integer 'odd? x))
  248.  
  249.   (number-dispatch x (error)
  250.     (##fixnum.odd? x)
  251.     (bignum-odd? x)
  252.     (error)
  253.     (if (flonum-int? x) (##odd? (##flonum.->exact-int x)) (error))
  254.     (if (cpxnum-int? x) (##odd? (cpxnum-real x)) (error))))
  255.  
  256. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  257.  
  258. ; Max and min
  259.  
  260. (define (##max x y)
  261.  
  262.   (define (error) (##trap-check-real 'max x y))
  263.  
  264.   (define (m x y) (if (##< x y) y x))
  265.  
  266.   (number-dispatch x (error)
  267.  
  268.     (number-dispatch y (error) ; x = fixnum
  269.       (m x y)
  270.       (m x y)
  271.       (m x y)
  272.       (if (##< x y) y (##flonum.<-fixnum x))
  273.       (if (cpxnum-real? y) (##max x (cpxnum-real y)) (error)))
  274.  
  275.     (number-dispatch y (error) ; x = bignum
  276.       (m x y)
  277.       (m x y)
  278.       (m x y)
  279.       (if (##< x y) y (##flonum.<-bignum x))
  280.       (if (cpxnum-real? y) (##max x (cpxnum-real y)) (error)))
  281.  
  282.     (number-dispatch y (error) ; x = ratnum
  283.       (m x y)
  284.       (m x y)
  285.       (m x y)
  286.       (if (##< x y) y (##flonum.<-ratnum x))
  287.       (if (cpxnum-real? y) (##max x (cpxnum-real y)) (error)))
  288.  
  289.     (number-dispatch y (error) ; x = flonum
  290.       (if (##< x y) (##flonum.<-fixnum y) x)
  291.       (if (##< x y) (##flonum.<-bignum y) x)
  292.       (if (##< x y) (##flonum.<-ratnum y) x)
  293.       (m x y)
  294.       (if (cpxnum-real? y) (##max x (cpxnum-real y)) (error)))
  295.  
  296.     (if (cpxnum-real? x) ; x = cpxnum
  297.       (number-dispatch y (error)
  298.         (##max (cpxnum-real x) y)
  299.         (##max (cpxnum-real x) y)
  300.         (##max (cpxnum-real x) y)
  301.         (##max (cpxnum-real x) y)
  302.         (if (cpxnum-real? y) (##max (cpxnum-real x) (cpxnum-real y)) (error)))
  303.       (error))))
  304.  
  305. (define (##min x y)
  306.  
  307.   (define (error) (##trap-check-real 'min x y))
  308.  
  309.   (define (m x y) (if (##< x y) x y))
  310.  
  311.   (number-dispatch x (error)
  312.  
  313.     (number-dispatch y (error) ; x = fixnum
  314.       (m x y)
  315.       (m x y)
  316.       (m x y)
  317.       (if (##< x y) (##flonum.<-fixnum x) y)
  318.       (if (cpxnum-real? y) (##min x (cpxnum-real y)) (error)))
  319.  
  320.     (number-dispatch y (error) ; x = bignum
  321.       (m x y)
  322.       (m x y)
  323.       (m x y)
  324.       (if (##< x y) (##flonum.<-bignum x) y)
  325.       (if (cpxnum-real? y) (##min x (cpxnum-real y)) (error)))
  326.  
  327.     (number-dispatch y (error) ; x = ratnum
  328.       (m x y)
  329.       (m x y)
  330.       (m x y)
  331.       (if (##< x y) (##flonum.<-ratnum x) y)
  332.       (if (cpxnum-real? y) (##min x (cpxnum-real y)) (error)))
  333.  
  334.     (number-dispatch y (error) ; x = flonum
  335.       (if (##< x y) x (##flonum.<-fixnum y))
  336.       (if (##< x y) x (##flonum.<-bignum y))
  337.       (if (##< x y) x (##flonum.<-ratnum y))
  338.       (m x y)
  339.       (if (cpxnum-real? y) (##min x (cpxnum-real y)) (error)))
  340.  
  341.     (if (cpxnum-real? x) ; x = cpxnum
  342.       (number-dispatch y (error)
  343.         (##min (cpxnum-real x) y)
  344.         (##min (cpxnum-real x) y)
  345.         (##min (cpxnum-real x) y)
  346.         (##min (cpxnum-real x) y)
  347.         (if (cpxnum-real? y) (##min (cpxnum-real x) (cpxnum-real y)) (error)))
  348.       (error))))
  349.  
  350. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  351.  
  352. ; +, *, -, /
  353.  
  354. (define (##+ x y)
  355.  
  356.   (define (error) (##trap-check-number '+ x y))
  357.  
  358.   (number-dispatch x (error)
  359.  
  360.     (number-dispatch y (error) ; x = fixnum
  361.       (##bignum.+/fixnum-fixnum x y)
  362.       (##bignum.+/bignum-fixnum y x)
  363.       (##ratnum.+ (##ratnum.<-exact-int x) y)
  364.       (##flonum.+ (##flonum.<-fixnum x) y)
  365.       (##cpxnum.+ (##cpxnum.<-non-cpxnum x) y))
  366.  
  367.     (number-dispatch y (error) ; x = bignum
  368.       (##bignum.+/bignum-fixnum x y)
  369.       (##bignum.+ x y)
  370.       (##ratnum.+ (##ratnum.<-exact-int x) y)
  371.       (##flonum.+ (##flonum.<-bignum x) y)
  372.       (##cpxnum.+ (##cpxnum.<-non-cpxnum x) y))
  373.  
  374.     (number-dispatch y (error) ; x = ratnum
  375.       (##ratnum.+ x (##ratnum.<-exact-int y))
  376.       (##ratnum.+ x (##ratnum.<-exact-int y))
  377.       (##ratnum.+ x y)
  378.       (##flonum.+ (##flonum.<-ratnum x) y)
  379.       (##cpxnum.+ (##cpxnum.<-non-cpxnum x) y))
  380.  
  381.     (number-dispatch y (error) ; x = flonum
  382.       (##flonum.+ x (##flonum.<-fixnum y))
  383.       (##flonum.+ x (##flonum.<-bignum y))
  384.       (##flonum.+ x (##flonum.<-ratnum y))
  385.       (##flonum.+ x y)
  386.       (##cpxnum.+ (##cpxnum.<-non-cpxnum x) y))
  387.  
  388.     (number-dispatch y (error) ; x = cpxnum
  389.       (##cpxnum.+ x (##cpxnum.<-non-cpxnum y))
  390.       (##cpxnum.+ x (##cpxnum.<-non-cpxnum y))
  391.       (##cpxnum.+ x (##cpxnum.<-non-cpxnum y))
  392.       (##cpxnum.+ x (##cpxnum.<-non-cpxnum y))
  393.       (##cpxnum.+ x y))))
  394.  
  395. (define (##* x y)
  396.  
  397.   (define (error) (##trap-check-number '* x y))
  398.  
  399.   (number-dispatch x (error)
  400.  
  401.     (number-dispatch y (error) ; x = fixnum
  402.       (##bignum.*/fixnum-fixnum x y)
  403.       (##bignum.*/bignum-fixnum y x)
  404.       (##ratnum.* (##ratnum.<-exact-int x) y)
  405.       (##flonum.* (##flonum.<-fixnum x) y)
  406.       (##cpxnum.* (##cpxnum.<-non-cpxnum x) y))
  407.  
  408.     (number-dispatch y (error) ; x = bignum
  409.       (##bignum.*/bignum-fixnum x y)
  410.       (##bignum.* x y)
  411.       (##ratnum.* (##ratnum.<-exact-int x) y)
  412.       (##flonum.* (##flonum.<-bignum x) y)
  413.       (##cpxnum.* (##cpxnum.<-non-cpxnum x) y))
  414.  
  415.     (number-dispatch y (error) ; x = ratnum
  416.       (##ratnum.* x (##ratnum.<-exact-int y))
  417.       (##ratnum.* x (##ratnum.<-exact-int y))
  418.       (##ratnum.* x y)
  419.       (##flonum.* (##flonum.<-ratnum x) y)
  420.       (##cpxnum.* (##cpxnum.<-non-cpxnum x) y))
  421.  
  422.     (number-dispatch y (error) ; x = flonum
  423.       (##flonum.* x (##flonum.<-fixnum y))
  424.       (##flonum.* x (##flonum.<-bignum y))
  425.       (##flonum.* x (##flonum.<-ratnum y))
  426.       (##flonum.* x y)
  427.       (##cpxnum.* (##cpxnum.<-non-cpxnum x) y))
  428.  
  429.     (number-dispatch y (error) ; x = cpxnum
  430.       (##cpxnum.* x (##cpxnum.<-non-cpxnum y))
  431.       (##cpxnum.* x (##cpxnum.<-non-cpxnum y))
  432.       (##cpxnum.* x (##cpxnum.<-non-cpxnum y))
  433.       (##cpxnum.* x (##cpxnum.<-non-cpxnum y))
  434.       (##cpxnum.* x y))))
  435.  
  436. (define (##- x y)
  437.  
  438.   (define (error) (##trap-check-number '- x y))
  439.  
  440.   (number-dispatch x (error)
  441.  
  442.     (number-dispatch y (error) ; x = fixnum
  443.       (##bignum.-/fixnum-fixnum x y)
  444.       (##bignum.-/fixnum-bignum x y)
  445.       (##ratnum.- (##ratnum.<-exact-int x) y)
  446.       (##flonum.- (##flonum.<-fixnum x) y)
  447.       (##cpxnum.- (##cpxnum.<-non-cpxnum x) y))
  448.  
  449.     (number-dispatch y (error) ; x = bignum
  450.       (##bignum.-/bignum-fixnum x y)
  451.       (##bignum.- x y)
  452.       (##ratnum.- (##ratnum.<-exact-int x) y)
  453.       (##flonum.- (##flonum.<-bignum x) y)
  454.       (##cpxnum.- (##cpxnum.<-non-cpxnum x) y))
  455.  
  456.     (number-dispatch y (error) ; x = ratnum
  457.       (##ratnum.- x (##ratnum.<-exact-int y))
  458.       (##ratnum.- x (##ratnum.<-exact-int y))
  459.       (##ratnum.- x y)
  460.       (##flonum.- (##flonum.<-ratnum x) y)
  461.       (##cpxnum.- (##cpxnum.<-non-cpxnum x) y))
  462.  
  463.     (number-dispatch y (error) ; x = flonum
  464.       (##flonum.- x (##flonum.<-fixnum y))
  465.       (##flonum.- x (##flonum.<-bignum y))
  466.       (##flonum.- x (##flonum.<-ratnum y))
  467.       (##flonum.- x y)
  468.       (##cpxnum.- (##cpxnum.<-non-cpxnum x) y))
  469.  
  470.     (number-dispatch y (error) ; x = cpxnum
  471.       (##cpxnum.- x (##cpxnum.<-non-cpxnum y))
  472.       (##cpxnum.- x (##cpxnum.<-non-cpxnum y))
  473.       (##cpxnum.- x (##cpxnum.<-non-cpxnum y))
  474.       (##cpxnum.- x (##cpxnum.<-non-cpxnum y))
  475.       (##cpxnum.- x y))))
  476.  
  477. (define (##/ x y)
  478.  
  479.   (define (divide-by-zero) (##trap-divide-by-zero '/ x y))
  480.  
  481.   (define (error) (##trap-check-number '/ x y))
  482.  
  483.   (number-dispatch y (error)
  484.  
  485.     (if (##fixnum.= y 0) ; y = fixnum
  486.       (divide-by-zero)
  487.       (number-dispatch x (error)
  488.         (##ratnum./ (##ratnum.<-exact-int x) (##ratnum.<-exact-int y))
  489.         (##ratnum./ (##ratnum.<-exact-int x) (##ratnum.<-exact-int y))
  490.         (##ratnum./ x (##ratnum.<-exact-int y))
  491.         (##flonum./ x (##flonum.<-fixnum y))
  492.         (##cpxnum./ x (##cpxnum.<-non-cpxnum y))))
  493.  
  494.     (number-dispatch x (error) ; y = bignum
  495.       (##ratnum./ (##ratnum.<-exact-int x) (##ratnum.<-exact-int y))
  496.       (##ratnum./ (##ratnum.<-exact-int x) (##ratnum.<-exact-int y))
  497.       (##ratnum./ x (##ratnum.<-exact-int y))
  498.       (##flonum./ x (##flonum.<-bignum y))
  499.       (##cpxnum./ x (##cpxnum.<-non-cpxnum y)))
  500.  
  501.     (number-dispatch x (error) ; y = ratnum
  502.       (##ratnum./ (##ratnum.<-exact-int x) y)
  503.       (##ratnum./ (##ratnum.<-exact-int x) y)
  504.       (##ratnum./ x y)
  505.       (##flonum./ x (##flonum.<-ratnum y))
  506.       (##cpxnum./ x (##cpxnum.<-non-cpxnum y)))
  507.  
  508.     (if (##flonum.zero? y) ; y = flonum
  509.       (divide-by-zero)
  510.       (number-dispatch x (error)
  511.         (##flonum./ (##flonum.<-fixnum x) y)
  512.         (##flonum./ (##flonum.<-bignum x) y)
  513.         (##flonum./ (##flonum.<-ratnum x) y)
  514.         (##flonum./ x y)
  515.         (##cpxnum./ x (##cpxnum.<-non-cpxnum y))))
  516.  
  517.     (let ((imag (cpxnum-imag y))) ; y = cpxnum
  518.       (if (and (flonum-zero? imag)
  519.                (let ((real (cpxnum-real y)))
  520.                  (non-cpxnum-zero? real)))
  521.         (divide-by-zero)
  522.         (number-dispatch x (error)
  523.           (##cpxnum./ (##cpxnum.<-non-cpxnum x) y)
  524.           (##cpxnum./ (##cpxnum.<-non-cpxnum x) y)
  525.           (##cpxnum./ (##cpxnum.<-non-cpxnum x) y)
  526.           (##cpxnum./ (##cpxnum.<-non-cpxnum x) y)
  527.           (##cpxnum./ x y))))))
  528.  
  529. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  530.  
  531. ; abs
  532.  
  533. (define (##abs x)
  534.  
  535.   (define (error) (##trap-check-real 'abs x))
  536.  
  537.   (number-dispatch x (error)
  538.     (if (##fixnum.negative? x) (##bignum.-/fixnum-fixnum 0 x) x)
  539.     (if (bignum-negative? x) (##bignum.-/fixnum-bignum 0 x) x)
  540.     (if (##negative? (ratnum-numerator x))
  541.       (ratnum-make (##- 0 (ratnum-numerator x)) (ratnum-denominator x))
  542.       x)
  543.     (##flonum.abs x)
  544.     (if (cpxnum-real? x) (##abs (cpxnum-real x)) (error))))
  545.  
  546. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  547.  
  548. ; quotient, remainder, modulo
  549.  
  550. (define (##quotient x y)
  551.  
  552.   (define (divide-by-zero) (##trap-divide-by-zero 'quotient x y))
  553.  
  554.   (define (error) (##trap-check-integer 'quotient x y))
  555.  
  556.   (define (inexact-quotient)
  557.     (##exact->inexact (##quotient (##inexact->exact x) (##inexact->exact y))))
  558.  
  559.   (number-dispatch y (error)
  560.  
  561.     (if (##fixnum.= y 0) ; y = fixnum
  562.       (divide-by-zero)
  563.       (number-dispatch x (error)
  564.         (if (##fixnum.= y -1)
  565.           (##bignum.-/fixnum-fixnum 0 x)
  566.           (##fixnum.quotient x y))
  567.         (##bignum.quotient/bignum-fixnum x y)
  568.         (error)
  569.         (if (flonum-int? x) (inexact-quotient) (error))
  570.         (if (cpxnum-int? x) (inexact-quotient) (error))))
  571.  
  572.     (number-dispatch x (error) ; y = bignum
  573.       (##bignum.quotient/fixnum-bignum x y)
  574.       (##bignum.quotient x y)
  575.       (error)
  576.       (if (flonum-int? x) (inexact-quotient) (error))
  577.       (if (cpxnum-int? x) (inexact-quotient) (error)))
  578.  
  579.     (error) ; y = ratnum
  580.  
  581.     (if (flonum-int? y) ; y = flonum
  582.       (number-dispatch x (error)
  583.         (inexact-quotient)
  584.         (inexact-quotient)
  585.         (error)
  586.         (if (flonum-int? x) (inexact-quotient) (error))
  587.         (if (cpxnum-int? x) (inexact-quotient) (error)))
  588.       (error))
  589.  
  590.     (if (cpxnum-int? y) ; y = cpxnum
  591.       (number-dispatch x (error)
  592.         (inexact-quotient)
  593.         (inexact-quotient)
  594.         (error)
  595.         (if (flonum-int? x) (inexact-quotient) (error))
  596.         (if (cpxnum-int? x) (inexact-quotient) (error)))
  597.       (error))))
  598.  
  599. (define (##remainder x y)
  600.  
  601.   (define (divide-by-zero) (##trap-divide-by-zero 'remainder x y))
  602.  
  603.   (define (error) (##trap-check-integer 'remainder x y))
  604.  
  605.   (define (inexact-remainder)
  606.     (##exact->inexact (##remainder (##inexact->exact x) (##inexact->exact y))))
  607.  
  608.   (number-dispatch y (error)
  609.  
  610.     (if (##fixnum.= y 0) ; y = fixnum
  611.       (divide-by-zero)
  612.       (number-dispatch x (error)
  613.         (##fixnum.remainder x y)
  614.         (##bignum.remainder/bignum-fixnum x y)
  615.         (error)
  616.         (if (flonum-int? x) (inexact-remainder) (error))
  617.         (if (cpxnum-int? x) (inexact-remainder) (error))))
  618.  
  619.     (number-dispatch x (error) ; y = bignum
  620.       (##bignum.remainder/fixnum-bignum x y)
  621.       (##bignum.remainder x y)
  622.       (error)
  623.       (if (flonum-int? x) (inexact-remainder) (error))
  624.       (if (cpxnum-int? x) (inexact-remainder) (error)))
  625.  
  626.     (error) ; y = ratnum
  627.  
  628.     (if (flonum-int? y) ; y = flonum
  629.       (number-dispatch x (error)
  630.         (inexact-remainder)
  631.         (inexact-remainder)
  632.         (error)
  633.         (if (flonum-int? x) (inexact-remainder) (error))
  634.         (if (cpxnum-int? x) (inexact-remainder) (error)))
  635.       (error))
  636.  
  637.     (if (cpxnum-int? y) ; y = cpxnum
  638.       (number-dispatch x (error)
  639.         (inexact-remainder)
  640.         (inexact-remainder)
  641.         (error)
  642.         (if (flonum-int? x) (inexact-remainder) (error))
  643.         (if (cpxnum-int? x) (inexact-remainder) (error)))
  644.       (error))))
  645.  
  646. (define (##modulo x y)
  647.  
  648.   (define (divide-by-zero) (##trap-divide-by-zero 'modulo x y))
  649.  
  650.   (define (error) (##trap-check-integer 'modulo x y))
  651.  
  652.   (define (inexact-modulo)
  653.     (##exact->inexact (##modulo (##inexact->exact x) (##inexact->exact y))))
  654.  
  655.   (number-dispatch y (error)
  656.  
  657.     (if (##fixnum.= y 0) ; y = fixnum
  658.       (divide-by-zero)
  659.       (number-dispatch x (error)
  660.         (##fixnum.modulo x y)
  661.         (##bignum.modulo/bignum-fixnum x y)
  662.         (error)
  663.         (if (flonum-int? x) (inexact-modulo) (error))
  664.         (if (cpxnum-int? x) (inexact-modulo) (error))))
  665.  
  666.     (number-dispatch x (error) ; y = bignum
  667.       (##bignum.modulo/fixnum-bignum x y)
  668.       (##bignum.modulo x y)
  669.       (error)
  670.       (if (flonum-int? x) (inexact-modulo) (error))
  671.       (if (cpxnum-int? x) (inexact-modulo) (error)))
  672.  
  673.     (error) ; y = ratnum
  674.  
  675.     (if (flonum-int? y) ; y = flonum
  676.       (number-dispatch x (error)
  677.         (inexact-modulo)
  678.         (inexact-modulo)
  679.         (error)
  680.         (if (flonum-int? x) (inexact-modulo) (error))
  681.         (if (cpxnum-int? x) (inexact-modulo) (error)))
  682.       (error))
  683.  
  684.     (if (cpxnum-int? y) ; y = cpxnum
  685.       (number-dispatch x (error)
  686.         (inexact-modulo)
  687.         (inexact-modulo)
  688.         (error)
  689.         (if (flonum-int? x) (inexact-modulo) (error))
  690.         (if (cpxnum-int? x) (inexact-modulo) (error)))
  691.       (error))))
  692.  
  693. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  694.  
  695. ; gcd, lcm
  696.  
  697. (define (##gcd x y)
  698.  
  699.   (define (exact-gcd x y)
  700.     (let loop ((x (##abs x)) (y (##abs y)))
  701.       (if (##eq? y 0) x (loop y (##remainder x y)))))
  702.  
  703.   (if (and (##integer? x) (##integer? y))
  704.     (if (and (##exact? x) (##exact? y))
  705.       (exact-gcd x y)
  706.       (##exact->inexact (exact-gcd (##inexact->exact x) (##inexact->exact y))))
  707.     (##trap-check-integer 'gcd x y)))
  708.  
  709. (define (##lcm x y)
  710.  
  711.   (define (exact-gcd x y)
  712.     (let loop ((x (##abs x)) (y (##abs y)))
  713.       (if (##eq? y 0) x (loop y (##remainder x y)))))
  714.  
  715.   (define (exact-lcm x y)
  716.     (if (or (##eq? x 0) (##eq? y 0))
  717.       0
  718.       (##quotient (##abs (##* x y)) (exact-gcd x y))))
  719.  
  720.   (if (and (##integer? x) (##integer? y))
  721.     (if (and (##exact? x) (##exact? y))
  722.       (exact-lcm x y)
  723.       (##exact->inexact (exact-lcm (##inexact->exact x) (##inexact->exact y))))
  724.     (##trap-check-integer 'lcm x y)))
  725.  
  726. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  727.  
  728. ; numerator, denominator
  729.  
  730. (define (##numerator x)
  731.  
  732.   (define (error) (##trap-check-rational 'numerator x))
  733.  
  734.   (number-dispatch x (error)
  735.     x
  736.     x
  737.     (ratnum-numerator x)
  738.     (##numerator (##flonum.inexact->exact x))
  739.     (if (cpxnum-real? x) (##numerator (cpxnum-real x)) (error))))
  740.  
  741. (define (##denominator x)
  742.  
  743.   (define (error) (##trap-check-rational 'denominator x))
  744.  
  745.   (number-dispatch x (error)
  746.     1
  747.     1
  748.     (ratnum-denominator x)
  749.     (##denominator (##flonum.inexact->exact x))
  750.     (if (cpxnum-real? x) (##denominator (cpxnum-real x)) (error))))
  751.  
  752. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  753.  
  754. ; floor, ceiling, truncate, round
  755.  
  756. (define (##floor x)
  757.  
  758.   (define (error) (##trap-check-real 'floor x))
  759.  
  760.   (number-dispatch x (error)
  761.     x
  762.     x
  763.     (##ratnum.floor x)
  764.     (##flonum.floor x)
  765.     (if (cpxnum-real? x) (##floor (cpxnum-real x)) (error))))
  766.  
  767. (define (##ceiling x)
  768.  
  769.   (define (error) (##trap-check-real 'ceiling x))
  770.  
  771.   (number-dispatch x (error)
  772.     x
  773.     x
  774.     (##ratnum.ceiling x)
  775.     (##flonum.ceiling x)
  776.     (if (cpxnum-real? x) (##ceiling (cpxnum-real x)) (error))))
  777.  
  778. (define (##truncate x)
  779.  
  780.   (define (error) (##trap-check-real 'truncate x))
  781.  
  782.   (number-dispatch x (error)
  783.     x
  784.     x
  785.     (##ratnum.truncate x)
  786.     (##flonum.truncate x)
  787.     (if (cpxnum-real? x) (##truncate (cpxnum-real x)) (error))))
  788.  
  789. (define (##round x)
  790.  
  791.   (define (error) (##trap-check-real 'round x))
  792.  
  793.   (number-dispatch x (error)
  794.     x
  795.     x
  796.     (##ratnum.round x)
  797.     (##flonum.round x)
  798.     (if (cpxnum-real? x) (##round (cpxnum-real x)) (error))))
  799.  
  800. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  801.  
  802. ; rationalize
  803.  
  804. (define (##rationalize x y)
  805.  
  806.   (define (simplest-rational1 x y)
  807.     (cond ((##< y x)
  808.            (simplest-rational2 y x))
  809.           ((##not (##< x y))
  810.            x)
  811.           ((##positive? x)
  812.            (simplest-rational2 x y))
  813.           ((##negative? y)
  814.            (##- 0 (simplest-rational2 (##- 0 y) (##- 0 x))))
  815.           (else
  816.            0)))
  817.  
  818.   (define (simplest-rational2 x y)
  819.     (let ((fx (##floor x))
  820.           (fy (##floor y)))
  821.       (cond ((##not (##< fx x))
  822.              fx)
  823.             ((##= fx fy)
  824.              (##+ fx
  825.                   (##/ 1
  826.                        (simplest-rational2
  827.                          (##/ 1 (##- y fy))
  828.                          (##/ 1 (##- x fx))))))
  829.             (else
  830.              (##+ fx 1)))))
  831.  
  832.   (if (and (##real? x) (##real? y))
  833.     (simplest-rational1 (##- x y) (##+ x y))
  834.     (##trap-check-real 'rationalize x y)))
  835.  
  836. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  837.  
  838. ; trigonometry and complex numbers
  839.  
  840. (define (##exp x)
  841.   (number-dispatch x (##trap-check-number 'exp x)
  842.     (if (##eq? x 0) 1 (##flonum.exp (##flonum.<-fixnum x)))
  843.     (##flonum.exp (##flonum.<-bignum x))
  844.     (##flonum.exp (##flonum.<-ratnum x))
  845.     (##flonum.exp x)
  846.     (##make-polar (##exp (cpxnum-real x)) (cpxnum-imag x))))
  847.  
  848. (define (##log x)
  849.  
  850.   (define (error) (##trap-check-range 'log x))
  851.  
  852.   (define (negative-log x)
  853.     (cpxnum-make (##log (##- 0 x)) (inexact-+pi)))
  854.  
  855.   (number-dispatch x (##trap-check-number 'log x)
  856.     (if (##fixnum.positive? x)
  857.       (if (##eq? x 1) 0 (##flonum.log (##flonum.<-fixnum x)))
  858.       (if (##fixnum.= x 0) (error) (negative-log x)))
  859.     (if (bignum-positive? x)
  860.       (##flonum.log (##flonum.<-bignum x))
  861.       (negative-log x))
  862.     (if (##positive? (ratnum-numerator x))
  863.       (##flonum.log (##flonum.<-ratnum x))
  864.       (negative-log x))
  865.     (if (##flonum.positive? x)
  866.       (##flonum.log x)
  867.       (if (##flonum.zero? x) (error) (negative-log x)))
  868.     (##make-rectangular (##log (##magnitude x)) (##angle x))))
  869.  
  870. (define (##sin x)
  871.   (number-dispatch x (##trap-check-number 'sin x)
  872.     (if (##eq? x 0) 0 (##flonum.sin (##flonum.<-fixnum x)))
  873.     (##flonum.sin (##flonum.<-bignum x))
  874.     (##flonum.sin (##flonum.<-ratnum x))
  875.     (##flonum.sin x)
  876.     (##/ (##- (##exp (cpxnum-make (##- 0 (cpxnum-imag x)) (cpxnum-real x)))
  877.               (##exp (cpxnum-make (cpxnum-imag x) (##- 0 (cpxnum-real x)))))
  878.          (cpxnum-+2i))))
  879.  
  880. (define (##cos x)
  881.   (number-dispatch x (##trap-check-number 'cos x)
  882.     (if (##eq? x 0) 1 (##flonum.cos (##flonum.<-fixnum x)))
  883.     (##flonum.cos (##flonum.<-bignum x))
  884.     (##flonum.cos (##flonum.<-ratnum x))
  885.     (##flonum.cos x)
  886.     (##/ (##+ (##exp (cpxnum-make (##- 0 (cpxnum-imag x)) (cpxnum-real x)))
  887.               (##exp (cpxnum-make (cpxnum-imag x) (##- 0 (cpxnum-real x)))))
  888.          2)))
  889.  
  890. (define (##tan x)
  891.   (number-dispatch x (##trap-check-number 'tan x)
  892.     (if (##eq? x 0) 0 (##flonum.tan (##flonum.<-fixnum x)))
  893.     (##flonum.tan (##flonum.<-bignum x))
  894.     (##flonum.tan (##flonum.<-ratnum x))
  895.     (##flonum.tan x)
  896.     (let ((a (##exp (cpxnum-make (##- 0 (cpxnum-imag x)) (cpxnum-real x))))
  897.           (b (##exp (cpxnum-make (cpxnum-imag x) (##- 0 (cpxnum-real x))))))
  898.       (let ((c (##/ (##- a b) (##+ a b))))
  899.         (##make-rectangular (##imag-part c) (##- 0 (##real-part c)))))))
  900.  
  901. (define (##asin x)
  902.  
  903.   (define (safe-case x)
  904.     (##* (cpxnum--i)
  905.          (##log (##+ (##* (cpxnum-+i) x)
  906.                      (##sqrt (##- 1 (##* x x)))))))
  907.  
  908.   (define (unsafe-case x)
  909.     (##- 0 (safe-case (##- 0 x))))
  910.  
  911.   (define (real-case x)
  912.     (cond ((##< x -1)
  913.            (unsafe-case x))
  914.           ((##< 1 x)
  915.            (safe-case x))
  916.           (else
  917.            (##flonum.asin (##exact->inexact x)))))
  918.  
  919.   (number-dispatch x (##trap-check-number 'asin x)
  920.     (if (##eq? x 0) 0 (real-case x))
  921.     (real-case x)
  922.     (real-case x)
  923.     (real-case x)
  924.     (let ((imag (cpxnum-imag x)))
  925.       (if (or (##positive? imag)
  926.               (and (flonum-zero? imag) (##negative? (cpxnum-real x))))
  927.         (unsafe-case x)
  928.         (safe-case x)))))
  929.  
  930. (define (##acos x)
  931.  
  932.   (define (complex-case x)
  933.     (##* (cpxnum--i)
  934.          (##log (##+ x
  935.                      (##* (cpxnum-+i) (##sqrt (##- 1 (##* x x))))))))
  936.  
  937.   (define (real-case x)
  938.     (if (or (##< x -1) (##< 1 x))
  939.       (complex-case x)
  940.       (##flonum.acos (##exact->inexact x))))
  941.  
  942.   (number-dispatch x (##trap-check-number 'acos x)
  943.     (if (##eq? x 0) 0 (real-case x))
  944.     (real-case x)
  945.     (real-case x)
  946.     (real-case x)
  947.     (complex-case x)))
  948.  
  949. (define (##atan x)
  950.   (number-dispatch x (##trap-check-number 'atan x)
  951.     (if (##eq? x 0) 0 (##flonum.atan (##flonum.<-fixnum x)))
  952.     (##flonum.atan (##flonum.<-bignum x))
  953.     (##flonum.atan (##flonum.<-ratnum x))
  954.     (##flonum.atan x)
  955.     (let ((a (cpxnum-make (##- 0 (cpxnum-imag x)) (cpxnum-real x))))
  956.       (##/ (##- (##log (##+ a 1)) (##log (##- 1 a)))
  957.            (cpxnum-+2i)))))
  958.  
  959. (define (##atan2 y x)
  960.   (if (and (##real? x) (##real? y))
  961.     (let ((x (##exact->inexact x)) (y (##exact->inexact y)))
  962.       (cond ((##flonum.positive? x)
  963.              (##flonum.atan (##flonum./ y x)))
  964.             ((##flonum.negative? y)
  965.              (if (##flonum.zero? x)
  966.                (inexact--pi/2)
  967.                (##flonum.+ (##flonum.atan (##flonum./ y x)) (inexact--pi))))
  968.             (else
  969.              (if (##flonum.zero? x)
  970.                (inexact-+pi/2)
  971.                (##flonum.+ (##flonum.atan (##flonum./ y x)) (inexact-+pi))))))
  972.     (##trap-check-real 'atan y x)))
  973.  
  974. (define (##sqrt x)
  975.  
  976.   (define (exact-int-sqrt x)
  977.     (cond ((##eq? x 0)
  978.            0)
  979.           ((##negative? x)
  980.            (cpxnum-make 0 (exact-int-sqrt (##- 0 x))))
  981.           (else
  982.            (let ((y (##exact-int.root x 2)))
  983.              (if (##= x (##* y y))
  984.                y
  985.                (##flonum.sqrt (##exact->inexact x)))))))
  986.  
  987.   (number-dispatch x (##trap-check-number 'sqrt x)
  988.     (exact-int-sqrt x)
  989.     (exact-int-sqrt x)
  990.     (##/ (exact-int-sqrt (ratnum-numerator x))
  991.          (exact-int-sqrt (ratnum-denominator x)))
  992.     (if (##flonum.negative? x)
  993.       (cpxnum-make 0 (##flonum.sqrt (##flonum.- (inexact-0) x)))
  994.       (##flonum.sqrt x))
  995.     (##make-polar (##sqrt (##magnitude x)) (##/ (##angle x) 2))))
  996.  
  997. (define (##expt x y)
  998.  
  999.   (define (error) (##trap-check-number 'expt x y))
  1000.  
  1001.   (define (general-expt x y)
  1002.     (##exp (##* (##log x) y)))
  1003.  
  1004.   (define (exact-int-expt x y)
  1005.     (cond ((##eq? y 0)
  1006.            1)
  1007.           ((or (##zero? x) (##= x 1))
  1008.            x)
  1009.           (else
  1010.            (let loop ((x x) (y y) (result 1))
  1011.              (if (##eq? y 1)
  1012.                (##* x result)
  1013.                (loop (##* x x)
  1014.                      (##quotient y 2)
  1015.                      (if (##odd? y) (##* x result) result)))))))
  1016.  
  1017.   (if (##complex? x)
  1018.     (cond ((exact-int? y)
  1019.            (if (##negative? y)
  1020.              (##/ 1 (exact-int-expt x (##- 0 y)))
  1021.              (exact-int-expt x y)))
  1022.           ((##complex? y)
  1023.            (cond ((##zero? y) (inexact-+1))
  1024.                  ((##zero? x) (if (##eq? x 0) 0 (inexact-0)))
  1025.                  (else        (general-expt x y))))
  1026.           (else
  1027.            (error)))
  1028.     (error)))
  1029.  
  1030. (define (##make-rectangular x y)
  1031.   (if (and (##real? x) (##real? y))
  1032.     (if (##eq? y 0)
  1033.       x
  1034.       (cpxnum-make (##real-part x) (##real-part y)))
  1035.     (##trap-check-real 'make-rectangular x y)))
  1036.  
  1037. (define (##make-polar x y)
  1038.   (if (and (##real? x) (##real? y))
  1039.     (let ((x* (##real-part x)) (y* (##real-part y)))
  1040.       (##make-rectangular (##* x* (##cos y*)) (##* x* (##sin y*))))
  1041.     (##trap-check-real 'make-polar x y)))
  1042.  
  1043. (define (##real-part x)
  1044.   (number-dispatch x (##trap-check-number 'real-part x)
  1045.     x x x x (cpxnum-real x)))
  1046.  
  1047. (define (##imag-part x)
  1048.   (number-dispatch x (##trap-check-number 'imag-part x)
  1049.     0 0 0 0 (cpxnum-imag x)))
  1050.  
  1051. (define (##magnitude x)
  1052.   (number-dispatch x (##trap-check-number 'magnitude x)
  1053.     (if (##fixnum.negative? x) (##bignum.-/fixnum-fixnum 0 x) x)
  1054.     (if (bignum-negative? x) (##bignum.-/fixnum-bignum 0 x) x)
  1055.     (if (##negative? (ratnum-numerator x))
  1056.       (ratnum-make (##- 0 (ratnum-numerator x)) (ratnum-denominator x))
  1057.       x)
  1058.     (##flonum.abs x)
  1059.     (let ((r (##abs (##real-part x))) (i (##abs (##imag-part x))))
  1060.       (define (complex-magn a b)
  1061.         (if (##zero? b)
  1062.           b
  1063.           (let ((c (##/ a b)))
  1064.             (##* b (##sqrt (##+ (##* c c) 1))))))
  1065.       (if (##< r i) (complex-magn r i) (complex-magn i r)))))
  1066.  
  1067. (define (##angle x)
  1068.   (number-dispatch x (##trap-check-number 'angle x)
  1069.     (if (##fixnum.negative? x) (inexact-+pi) 0)
  1070.     (if (bignum-negative? x) (inexact-+pi) 0)
  1071.     (if (##negative? (ratnum-numerator x)) (inexact-+pi) 0)
  1072.     (if (##flonum.negative? x) (inexact-+pi) (inexact-0))
  1073.     (if (##zero? x)
  1074.       (inexact-0)
  1075.       (##atan2 (cpxnum-imag x) (cpxnum-real x)))))
  1076.  
  1077. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1078.  
  1079. ; exact->inexact, inexact->exact
  1080.  
  1081. (define (##exact->inexact x)
  1082.   (number-dispatch x (##trap-check-number 'exact->inexact x)
  1083.     (##flonum.<-fixnum x)
  1084.     (##flonum.<-bignum x)
  1085.     (##flonum.<-ratnum x)
  1086.     x
  1087.     (##make-rectangular (##exact->inexact (cpxnum-real x))
  1088.                         (##exact->inexact (cpxnum-imag x)))))
  1089.  
  1090. (define (##inexact->exact x)
  1091.   (number-dispatch x (##trap-check-number 'inexact->exact x)
  1092.     x
  1093.     x
  1094.     x
  1095.     (##flonum.inexact->exact x)
  1096.     (##make-rectangular (##inexact->exact (cpxnum-real x))
  1097.                         (##inexact->exact (cpxnum-imag x)))))
  1098.  
  1099. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1100.  
  1101. ; number->string, string->number
  1102.  
  1103. (define (##number->string x rad)
  1104.  
  1105.   (define (non-cpxnum->string x)
  1106.     (cond ((exact-int? x)
  1107.            (##exact-int.number->string x rad))
  1108.           ((##ratnum? x)
  1109.            (##string-append (##exact-int.number->string (ratnum-numerator x) rad)
  1110.                             "/"
  1111.                             (##exact-int.number->string (ratnum-denominator x) rad)))
  1112.           ((##flonum? x)
  1113.            (##flonum.number->string x))
  1114.           (else
  1115.            (##trap-check-number 'number->string x rad))))
  1116.  
  1117.   (if (or (##eq? rad 2)
  1118.           (##eq? rad 8)
  1119.           (##eq? rad 10)
  1120.           (##eq? rad 16))
  1121.     (if (##cpxnum? x)
  1122.       (let* ((real (cpxnum-real x))
  1123.              (real-str (if (##eq? real 0) "" (non-cpxnum->string real))))
  1124.         (let ((imag (cpxnum-imag x)))
  1125.           (cond ((##eq? imag 1)
  1126.                  (##string-append real-str "+i"))
  1127.                 ((##eq? imag -1)
  1128.                  (##string-append real-str "-i"))
  1129.                 ((##negative? imag)
  1130.                  (##string-append real-str (non-cpxnum->string imag) "i"))
  1131.                 (else
  1132.                  (##string-append real-str "+" (non-cpxnum->string imag) "i")))))
  1133.       (non-cpxnum->string x))
  1134.     (##trap-check-range 'number->string x rad)))
  1135.  
  1136. (define (##exact-int.number->string x rad)
  1137.   (if (##fixnum? x)
  1138.     (##fixnum.number->string x rad)
  1139.     (##bignum.number->string x rad)))
  1140.  
  1141. (define (##flonum.number->string x)
  1142.  
  1143.   (define (num->str x)
  1144.     (let ((z (##flonum.->exact-exponential-format x)))
  1145.       (##flonum.printout (##car z) (##cdr z))))
  1146.  
  1147.   (cond ((##flonum.zero? x)
  1148.          "0.")
  1149.         ((##flonum.negative? x)
  1150.          (##string-append "-" (num->str (##flonum.abs x))))
  1151.         (else
  1152.          (num->str x))))
  1153.  
  1154. (##define-macro (two) 2)
  1155. (##define-macro (ten) 10)
  1156. (##define-macro (ten-minus-1) 9)
  1157.  
  1158. (define (##flonum.printout m e)
  1159.  
  1160.   (define (done h k d)
  1161.     (let ((str (##exact-int.number->string d (ten))))
  1162.       (cond ((and (##fixnum.< h -1)
  1163.                   (or ; (##fixnum.< -5 h)
  1164.                       (##fixnum.< (##fixnum.- 0 (flonum-max-digits)) k)))
  1165.              (##string-append "."
  1166.                               (##make-string (##fixnum.- -1 h) #\0)
  1167.                               str))
  1168.             ((and (##fixnum.< 0 k)
  1169.                   (or ; (##fixnum.< k 3)
  1170.                       (##fixnum.< h (flonum-max-digits))))
  1171.              (##string-append str
  1172.                               (##make-string k #\0)
  1173.                               "."))
  1174.             ((and (##fixnum.< -2 h) (##fixnum.< k 1))
  1175.              (let ((n (##fixnum.+ h 1)))
  1176.                (##string-append (##substring str 0 n)
  1177.                                 "."
  1178.                                 (##substring str n (##string-length str)))))
  1179.             (else
  1180.              (##string-append (##substring str 0 1)
  1181.                               "."
  1182.                               (##substring str 1 (##string-length str))
  1183.                               "e"
  1184.                               (##exact-int.number->string h (ten)))))))
  1185.  
  1186.   (define (fixup-loop1 k r s ceiling-s-div-ten m- m+)
  1187.     (if (##< r ceiling-s-div-ten)
  1188.       (fixup-loop1 (##fixnum.- k 1)
  1189.                    (##* r (ten))
  1190.                    s
  1191.                    ceiling-s-div-ten
  1192.                    (##* m- (ten))
  1193.                    (##* m+ (ten)))
  1194.       (let fixup-loop2 ((k k) (r r) (s s) (m- m-) (m+ m+))
  1195.         (if (##not (##< (##+ (##* r 2) m+) (##* s 2)))
  1196.           (fixup-loop2 (##fixnum.+ k 1) r (##* s (ten)) m- m+)
  1197.           (let ((h (##fixnum.- k 1)))
  1198.             (let ((ur (##exact-int.div (##* r (ten)) s)))
  1199.               (let loop ((k (##fixnum.- k 1))
  1200.                          (u (##car ur))
  1201.                          (r (##cdr ur))
  1202.                          (m- (##* m- (ten)))
  1203.                          (m+ (##* m+ (ten)))
  1204.                          (d 0))
  1205.                 (let ((r*2 (##* r 2)) (s*2 (##* s 2)))
  1206.                   (cond ((##< r*2 m-)
  1207.                          (if (##< (##- s*2 m+) r*2)
  1208.                            (if (##not (##< s r*2))
  1209.                              (done h k (##+ d u))
  1210.                              (done h k (##+ d (##fixnum.+ u 1))))
  1211.                            (done h k (##+ d u))))
  1212.                         ((##< (##- s*2 m+) r*2)
  1213.                          (done h k (##+ d (##fixnum.+ u 1))))
  1214.                         (else
  1215.                          (let ((ur (##exact-int.div (##* r (ten)) s)))
  1216.                            (loop (##fixnum.- k 1)
  1217.                                  (##car ur)
  1218.                                  (##cdr ur)
  1219.                                  (##* m- (ten))
  1220.                                  (##* m+ (ten))
  1221.                                  (##* (##+ d u) (ten))))))))))))))
  1222.  
  1223.   (define (fixup r s m-)
  1224.     (if (##= m (flonum-+m-min))
  1225.       (let ((r* (##* r (two)))
  1226.             (s* (##* s (two)))
  1227.             (m+ (##* m- (two))))
  1228.         (fixup-loop1 0 r* s* (##quotient (##+ s* (ten-minus-1)) (ten)) m- m+))
  1229.       (fixup-loop1 0 r s (##quotient (##+ s (ten-minus-1)) (ten)) m- m-)))
  1230.  
  1231.   (if (##fixnum.negative? e)
  1232.     (fixup m (##expt (two) (##fixnum.- 0 e)) 1)
  1233.     (let ((two-to-the-e (##expt (two) e)))
  1234.       (fixup (##* m two-to-the-e) 1 two-to-the-e))))
  1235.  
  1236. (define (##string->number s rad)
  1237.  
  1238.   (define (make-real e n r p)       ; Note: this algorithm does not satisfy the
  1239.     (let ((x (##* n (##expt r p)))) ; accuracy required by the IEEE standard
  1240.       (if (##eq? e 'E) x (##exact->inexact x))))
  1241.  
  1242.   (define (make-rec a b)
  1243.     (##make-rectangular a b))
  1244.  
  1245.   (define (make-pol a b)
  1246.     (##make-polar a b))
  1247.  
  1248.   (define (ex e x)
  1249.     (if (##eq? e 'I) (##exact->inexact x) x))
  1250.  
  1251.   (define (end s i x)
  1252.     (if (##eq? i (##string-length s)) x #f))
  1253.  
  1254.   (define (radix-prefix s i)
  1255.     (if (##fixnum.< (##fixnum.+ i 1) (##string-length s))
  1256.       (if (##char=? (##string-ref s i) #\#)
  1257.         (let ((c (##string-ref s (##fixnum.+ i 1))))
  1258.           (cond ((or (##char=? c #\b) (##char=? c #\B))  2)
  1259.                 ((or (##char=? c #\o) (##char=? c #\O))  8)
  1260.                 ((or (##char=? c #\d) (##char=? c #\D)) 10)
  1261.                 ((or (##char=? c #\x) (##char=? c #\X)) 16)
  1262.                 (else                                   #f)))
  1263.         #f)
  1264.       #f))
  1265.  
  1266.   (define (exactness-prefix s i)
  1267.     (if (##fixnum.< (##fixnum.+ i 1) (##string-length s))
  1268.       (if (##char=? (##string-ref s i) #\#)
  1269.         (let ((c (##string-ref s (##fixnum.+ i 1))))
  1270.           (cond ((or (##char=? c #\i) (##char=? c #\I)) 'I)
  1271.                 ((or (##char=? c #\e) (##char=? c #\E)) 'E)
  1272.                 (else                                   #f)))
  1273.         #f)
  1274.       #f))
  1275.  
  1276.   (define (sign s i)
  1277.     (if (##fixnum.< i (##string-length s))
  1278.       (let ((c (##string-ref s i)))
  1279.         (cond ((##char=? c #\+) '+)
  1280.               ((##char=? c #\-) '-)
  1281.               (else             #f)))
  1282.       #f))
  1283.  
  1284.   (define (imaginary s i)
  1285.     (if (##fixnum.< i (##string-length s))
  1286.       (let ((c (##string-ref s i)))
  1287.         (or (##char=? c #\i) (##char=? c #\I)))
  1288.       #f))
  1289.  
  1290.   (define (polar s i)
  1291.     (if (##fixnum.< i (##string-length s))
  1292.       (##char=? (##string-ref s i) #\@)
  1293.       #f))
  1294.  
  1295.   (define (ratio s i)
  1296.     (if (##fixnum.< i (##string-length s))
  1297.       (##char=? (##string-ref s i) #\/)
  1298.       #f))
  1299.  
  1300.   (define (exponent s i)
  1301.     (if (##fixnum.< i (##string-length s))
  1302.       (let ((c (##string-ref s i)))
  1303.         (cond ((or (##char=? c #\e) (##char=? c #\E)) 'E)
  1304.               ((or (##char=? c #\s) (##char=? c #\S)) 'S)
  1305.               ((or (##char=? c #\f) (##char=? c #\F)) 'F)
  1306.               ((or (##char=? c #\d) (##char=? c #\D)) 'D)
  1307.               ((or (##char=? c #\l) (##char=? c #\L)) 'L)
  1308.               (else                                   #f)))
  1309.       #f))
  1310.  
  1311.   (define (digit c r)
  1312.     (let ((d (cond ((##not (or (##char<? c #\0) (##char<? #\9 c)))
  1313.                     (##fixnum.- (##char->integer c) 48))
  1314.                    ((##not (or (##char<? c #\a) (##char<? #\z c)))
  1315.                     (##fixnum.- (##char->integer c) 87))
  1316.                    ((##not (or (##char<? c #\A) (##char<? #\Z c)))
  1317.                     (##fixnum.- (##char->integer c) 55))
  1318.                    (else
  1319.                     #f))))
  1320.       (if (and d (##fixnum.< d r)) d #f)))
  1321.  
  1322.   (define (prefix s i r cont)
  1323.     (let ((e1 (exactness-prefix s i)))
  1324.       (if e1
  1325.         (let ((r1 (radix-prefix s (##fixnum.+ i 2))))
  1326.           (if r1
  1327.             (cont s (##fixnum.+ i 4) r1 e1)
  1328.             (cont s (##fixnum.+ i 2) r e1)))
  1329.         (let ((r2 (radix-prefix s i)))
  1330.           (if r2
  1331.             (let ((e2 (exactness-prefix s (##fixnum.+ i 2))))
  1332.               (if e2
  1333.                 (cont s (##fixnum.+ i 4) r2 e2)
  1334.                 (cont s (##fixnum.+ i 2) r2 #f)))
  1335.             (cont s i r #f))))))
  1336.  
  1337.   (define (num s i r)
  1338.     (prefix s i r complex))
  1339.  
  1340.   (define (complex s i r e)
  1341.     (let ((+/- (sign s i)))
  1342.       (ucomplex s (if +/- (##fixnum.+ i 1) i) r e +/-)))
  1343.  
  1344.   (define (ucomplex s i r e +/-)
  1345.     (if (and +/- (imaginary s i))
  1346.       (end s (##fixnum.+ i 1)
  1347.         (make-rec (ex e 0) (ex e (if (##eq? +/- '-) -1 1))))
  1348.       (ureal s i r e +/- #f
  1349.         (lambda (s i r e +/- dummy x)
  1350.           (let ((y (if (##eq? +/- '-) (##- 0 x) x)))
  1351.             (cond ((and +/- (imaginary s i))
  1352.                    (end s (##fixnum.+ i 1) (make-rec (ex e 0) y)))
  1353.                   ((polar s i)
  1354.                    (let ((+/-2 (sign s (##fixnum.+ i 1))))
  1355.                      (ureal s (##fixnum.+ i (if +/-2 2 1)) r e +/-2 y
  1356.                        (lambda (s i r e +/-2 y z)
  1357.                          (end s i
  1358.                            (make-pol y (if (##eq? +/-2 '-) (##- 0 z) z)))))))
  1359.                   (else
  1360.                    (let ((+/-2 (sign s i)))
  1361.                      (if +/-2
  1362.                        (if (imaginary s (##fixnum.+ i 1))
  1363.                          (end s (##fixnum.+ i 2)
  1364.                            (make-rec y (ex e (if (##eq? +/-2 '-) -1 1))))
  1365.                          (ureal s (##fixnum.+ i 1) r e +/-2 y
  1366.                            (lambda (s i r e +/-2 y z)
  1367.                              (and (imaginary s i)
  1368.                                   (end s (##fixnum.+ i 1)
  1369.                                     (make-rec y (if (##eq? +/-2 '-) (##- 0 z) z)))))))
  1370.                        (end s i y))))))))))
  1371.  
  1372.   (define (ureal s i r e +/- x cont)
  1373.     (uinteger s i r e +/- x cont (##eq? r 10)
  1374.       (lambda (s i r e +/- x cont ex? n p)
  1375.         (if p ; decimal point or exponent?
  1376.           (cont s i r e +/- x (make-real e n r p))
  1377.           (if (ratio s i)
  1378.             (uinteger s (##fixnum.+ i 1) r e +/- x cont #f
  1379.               (lambda (s i r e +/- x cont ex2? n2 p2)
  1380.                 (let ((y (##/ n n2)))
  1381.                   (cont s i r e +/- x (ex (or e (if (and ex? ex2?) #f 'I)) y)))))
  1382.             (cont s i r e +/- x (ex (or e (if ex? #f 'I)) n)))))))
  1383.  
  1384.   (define (uinteger s i r a1 a2 a3 a4 decimal? cont)
  1385.     (let loop1 ((i i) (state 0) (n 0) (p #f))
  1386.  
  1387.       (define (suffix)
  1388.         (if (##eq? state 0)
  1389.           #f
  1390.           (let ((mark (exponent s i)))
  1391.             (if (and mark decimal?)
  1392.               (let ((+/- (sign s (##fixnum.+ i 1))) (p (or p 0)))
  1393.                 (let loop2 ((i (##fixnum.+ i (if +/- 2 1))) (j #f))
  1394.                   (if (and (##fixnum.< i (##string-length s))
  1395.                            (digit (##string-ref s i) 10))
  1396.                     (loop2 (##fixnum.+ i 1)
  1397.                            (##+ (##* (or j 0) 10)
  1398.                                 (digit (##string-ref s i) 10)))
  1399.                     (and j (cont s i r a1 a2 a3 a4 #f n
  1400.                              (##+ p (if (##eq? +/- '-) (##- 0 j) j)))))))
  1401.               (cont s i r a1 a2 a3 a4 (##not (or (##eq? state 2) p)) n p)))))
  1402.  
  1403.       (if (##fixnum.< i (##string-length s))
  1404.         (let ((c (##string-ref s i)))
  1405.           (if (and (##char=? c #\.) decimal? (##not p))
  1406.             (loop1 (##fixnum.+ i 1) state n 0)
  1407.             (if (and (##char=? c #\#) (##fixnum.< 0 state))
  1408.               (loop1 (##fixnum.+ i 1) 2 (##* n r) (and p (##fixnum.- p 1)))
  1409.               (if (##fixnum.< state 2)
  1410.                 (let ((d (digit c r)))
  1411.                   (if d
  1412.                     (loop1 (##fixnum.+ i 1)
  1413.                            1
  1414.                            (##+ (##* n r) d)
  1415.                            (and p (##fixnum.- p 1)))
  1416.                     (suffix)))
  1417.                 (suffix)))))
  1418.         (suffix))))
  1419.  
  1420.   (if (or (##eq? rad 2)
  1421.           (##eq? rad 8)
  1422.           (##eq? rad 10)
  1423.           (##eq? rad 16))
  1424.  
  1425.     (num s 0 rad)
  1426.  
  1427.     (##trap-check-range 'string->number s rad)))
  1428.  
  1429. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1430.  
  1431. ; ##logior, ##logxor, ##logand, ##lognot, ##ash
  1432.  
  1433. (define-nary0 (##fixnum.logior x y)  0 x (##fixnum.logior x y) no-touch)
  1434. (define-nary0 (##fixnum.logxor x y)  0 x (##fixnum.logxor x y) no-touch)
  1435. (define-nary0 (##fixnum.logand x y) -1 x (##fixnum.logand x y) no-touch)
  1436. (define-system (##fixnum.lognot x) (##fixnum.- -1 x))
  1437. (define-system (##fixnum.ash x y))
  1438. (define-system (##fixnum.lsh x y))
  1439.  
  1440. (define-nary0 (##logior x y)  0 x (####logior x y) touch-vars)
  1441. (define-nary0 (##logxor x y)  0 x (####logxor x y) touch-vars)
  1442. (define-nary0 (##logand x y) -1 x (####logand x y) touch-vars)
  1443. (define (##lognot x) (touch-vars (x) (####lognot x)))
  1444. (define (##ash x y) (touch-vars (x y) (####ash x y)))
  1445.  
  1446. (define (####logior x y)
  1447.  
  1448.   (define (otherwise x y)
  1449.     (##trap-check-integer '##logior x y))
  1450.  
  1451.   (cond ((##fixnum? y)
  1452.          (cond ((##fixnum? x)
  1453.                 (##fixnum.logior x y))
  1454.                ((##bignum? x)
  1455.                 (##bignum.logior/bignum-fixnum x y))
  1456.                (else
  1457.                 (otherwise x y))))
  1458.         ((##bignum? y)
  1459.          (cond ((##fixnum? x)
  1460.                 (##bignum.logior/bignum-fixnum y x))
  1461.                ((##bignum? x)
  1462.                 (##bignum.logior x y))
  1463.                (else
  1464.                 (otherwise x y))))
  1465.         (else
  1466.          (otherwise x y))))
  1467.  
  1468. (define (####logxor x y)
  1469.  
  1470.   (define (otherwise x y)
  1471.     (##trap-check-integer '##logxor x y))
  1472.  
  1473.   (cond ((##fixnum? y)
  1474.          (cond ((##fixnum? x)
  1475.                 (##fixnum.logxor x y))
  1476.                ((##bignum? x)
  1477.                 (##bignum.logxor/bignum-fixnum x y))
  1478.                (else
  1479.                 (otherwise x y))))
  1480.         ((##bignum? y)
  1481.          (cond ((##fixnum? x)
  1482.                 (##bignum.logxor/bignum-fixnum y x))
  1483.                ((##bignum? x)
  1484.                 (##bignum.logxor x y))
  1485.                (else
  1486.                 (otherwise x y))))
  1487.         (else
  1488.          (otherwise x y))))
  1489.  
  1490. (define (####logand x y)
  1491.  
  1492.   (define (otherwise x y)
  1493.     (##trap-check-integer '##logand x y))
  1494.  
  1495.   (cond ((##fixnum? y)
  1496.          (cond ((##fixnum? x)
  1497.                 (##fixnum.logand x y))
  1498.                ((##bignum? x)
  1499.                 (##bignum.logand/bignum-fixnum x y))
  1500.                (else
  1501.                 (otherwise x y))))
  1502.         ((##bignum? y)
  1503.          (cond ((##fixnum? x)
  1504.                 (##bignum.logand/bignum-fixnum y x))
  1505.                ((##bignum? x)
  1506.                 (##bignum.logand x y))
  1507.                (else
  1508.                 (otherwise x y))))
  1509.         (else
  1510.          (otherwise x y))))
  1511.  
  1512. (define (####lognot x)
  1513.  
  1514.   (define (otherwise x)
  1515.     (##trap-check-integer '##lognot x))
  1516.  
  1517.   (cond ((##fixnum? x)
  1518.          (##fixnum.lognot x))
  1519.         ((##bignum? x)
  1520.          (##bignum.-/fixnum-bignum -1 x))
  1521.         (else
  1522.          (otherwise x))))
  1523.  
  1524. (define (####ash x y)
  1525.  
  1526.   (define (otherwise x y)
  1527.     (##trap-check-integer '##ash x y))
  1528.  
  1529.   (cond ((##fixnum? y)
  1530.          (cond ((##fixnum? x)
  1531.                 (##bignum.ash/fixnum-fixnum x y))
  1532.                ((##bignum? x)
  1533.                 (##bignum.ash/bignum-fixnum x y))
  1534.                (else
  1535.                 (otherwise x y))))
  1536.         ((##bignum? y)
  1537.          (cond ((##fixnum? x)
  1538.                 (##bignum.ash/fixnum-bignum x y))
  1539.                ((##bignum? x)
  1540.                 (##bignum.ash x y))
  1541.                (else
  1542.                 (otherwise x y))))
  1543.         (else
  1544.          (otherwise x y))))
  1545.  
  1546. (define (##bignum.logior/bignum-fixnum x y)
  1547.   (##bignum.logior x (##bignum.<-fixnum y)))
  1548.  
  1549. (define (##bignum.logxor/bignum-fixnum x y)
  1550.   (##bignum.logxor x (##bignum.<-fixnum y)))
  1551.  
  1552. (define (##bignum.logand/bignum-fixnum x y)
  1553.   (##bignum.logand x (##bignum.<-fixnum y)))
  1554.  
  1555. (define (##bignum.ash/fixnum-fixnum x y)
  1556.   (##bignum.ash (##bignum.<-fixnum x) (##bignum.<-fixnum y)))
  1557.  
  1558. (define (##bignum.ash/bignum-fixnum x y)
  1559.   (##bignum.ash x (##bignum.<-fixnum y)))
  1560.  
  1561. (define (##bignum.ash/fixnum-bignum x y)
  1562.   (##bignum.ash (##bignum.<-fixnum x) y))
  1563.  
  1564. (define (##bignum.logior x y)
  1565.   (##trap-unimplemented '##logior x y))
  1566.  
  1567. (define (##bignum.logxor x y)
  1568.   (##trap-unimplemented '##logxor x y))
  1569.  
  1570. (define (##bignum.logand x y)
  1571.   (##trap-unimplemented '##logand x y))
  1572.  
  1573. (define (##bignum.ash x y)
  1574.   (##trap-unimplemented '##ash x y))
  1575.  
  1576. ; other utilities
  1577.  
  1578. (define (##exact-int.width x)
  1579.   (if (##fixnum? x)
  1580.     (##fixnum.width x)
  1581.     (##bignum.width x)))
  1582.  
  1583. (define (##fixnum.width x)
  1584.   (if (##fixnum.negative? x)
  1585.     (let loop1 ((w 0) (x x))
  1586.       (if (##fixnum.< x -1) (loop1 (##fixnum.+ w 1) (##fixnum.ash x -1)) w))
  1587.     (let loop2 ((w 0) (x x))
  1588.       (if (##fixnum.< 0 x) (loop2 (##fixnum.+ w 1) (##fixnum.ash x -1)) w))))
  1589.  
  1590. (define (##bignum.width x)
  1591.   (if (bignum-negative? x)
  1592.     (##bignum.width (##- -1 x)) ; lazy...
  1593.     (let ((len (bignum-length x)))
  1594.       (##fixnum.+ (##fixnum.* (##fixnum.- len 2) (radix-width))
  1595.                   (##fixnum.width (bignum-digit-ref x (##fixnum.- len 1)))))))
  1596.  
  1597. (define (##exact-int.root x y)
  1598.   (let loop ((g (##expt 2
  1599.                         (##quotient (##+ (##exact-int.width x) (##- y 1)) y))))
  1600.     (let ((a (##expt g (##- y 1))))
  1601.       (let ((b (##* a y)))
  1602.         (let ((c (##* a (##- y 1))))
  1603.           (let ((d (##quotient (##+ x (##* g c)) b)))
  1604.             (if (##< d g) (loop d) g)))))))
  1605.  
  1606. (define (##exact-int.div x y)
  1607.  
  1608.   (define (div x y)
  1609.     (let ((z (##bignum.div x y)))
  1610.       (##set-car! z (##bignum.normalize (##car z)))
  1611.       (##set-cdr! z (##bignum.normalize (##cdr z)))
  1612.       z))
  1613.  
  1614.   (if (##fixnum? x)
  1615.     (if (##fixnum? y)
  1616.       (##cons (##fixnum.quotient x y) (##fixnum.remainder x y))
  1617.       (div (##bignum.<-fixnum x) y))
  1618.     (if (##fixnum? y)
  1619.       (div x (##bignum.<-fixnum y))
  1620.       (div x y))))
  1621.  
  1622. ;------------------------------------------------------------------------------
  1623.  
  1624. ; Fixnum operations
  1625. ; -----------------
  1626.  
  1627. (define-system (##fixnum.zero? x)
  1628.   (##eq? x 0))
  1629.  
  1630. (define-system (##fixnum.positive? x)
  1631.   (##fixnum.< 0 x))
  1632.  
  1633. (define-system (##fixnum.negative? x)
  1634.   (##fixnum.< x 0))
  1635.  
  1636. (define-system (##fixnum.odd? x)
  1637.   (##eq? (##fixnum.modulo x 2) 1))
  1638.  
  1639. (define-system (##fixnum.even? x)
  1640.   (##eq? (##fixnum.modulo x 2) 0))
  1641.  
  1642. (define-nary0-boolean (##fixnum.= x y)
  1643.   (##eq? x y) no-check no-touch)
  1644.  
  1645. (define-nary0-boolean (##fixnum.< x y)
  1646.   (##fixnum.< x y) no-check no-touch)
  1647.  
  1648. (define-nary0-boolean (##fixnum.> x y)
  1649.   (##fixnum.< y x) no-check no-touch)
  1650.  
  1651. (define-nary0-boolean (##fixnum.<= x y)
  1652.   (##not (##fixnum.< y x)) no-check no-touch)
  1653.  
  1654. (define-nary0-boolean (##fixnum.>= x y)
  1655.   (##not (##fixnum.< x y)) no-check no-touch)
  1656.  
  1657. (define-nary0 (##fixnum.+ x y) 0 x (##fixnum.+ x y) no-touch)
  1658. (define-nary0 (##fixnum.* x y) 1 x (##fixnum.* x y) no-touch)
  1659. (define-nary1 (##fixnum.- x y) (##fixnum.- 0 x) (##fixnum.- x y) no-touch)
  1660.  
  1661. (define-system (##fixnum.quotient x y))
  1662.  
  1663. (define-system (##fixnum.remainder x y)
  1664.   (##fixnum.- x (##fixnum.* (##fixnum.quotient x y) y)))
  1665.  
  1666. (define-system (##fixnum.modulo x y)
  1667.   (let ((r (##fixnum.remainder x y)))
  1668.     (if (##eq? r 0)
  1669.       0
  1670.       (if (##fixnum.< x 0)
  1671.         (if (##fixnum.< y 0) r (##fixnum.+ r y))
  1672.         (if (##fixnum.< y 0) (##fixnum.+ r y) r)))))
  1673.  
  1674. (define (##fixnum.number->string n rad)
  1675.  
  1676.   (define (loop k n i)
  1677.     (let ((x (##fixnum.quotient n rad)))
  1678.       (let ((s (if (##eq? x 0)
  1679.                  (##make-string (##fixnum.+ i k) #\space)
  1680.                  (loop k x (##fixnum.+ i 1)))))
  1681.         (##string-set! s
  1682.                        (##fixnum.- (##string-length s) i)
  1683.                        (##string-ref "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  1684.                                      (##fixnum.- 0 (##fixnum.remainder n rad)))))))
  1685.  
  1686.   (if (##fixnum.< n 0)
  1687.     (##string-set! (loop 1 n 1) 0 #\-)
  1688.     (loop 0 (##fixnum.- 0 n) 1)))
  1689.  
  1690. ;------------------------------------------------------------------------------
  1691.  
  1692. ; Bignum operations
  1693. ; -----------------
  1694.  
  1695. ; Bignums are represented with 'word' vectors:
  1696. ;
  1697. ; assuming that the bignum 'n' is represented by the word vector 'v' of
  1698. ; length 'l', we have
  1699. ;
  1700. ;                       l-2
  1701. ;                      -----
  1702. ;                      \                   i
  1703. ; n  =  (v[0]*2-1)  *   >   v[i+1] * radix
  1704. ;                      /
  1705. ;                      -----
  1706. ;                      i = 0
  1707. ;
  1708. ; note: v[0] = 0 if number is negative, v[0] = 1 if number is positive.
  1709. ;
  1710. ; 'radix' must be less than or equal to sqrt(max fixnum)+1.  This guarantees
  1711. ; that the result of an arithmetic operation on bignum digits will be a fixnum
  1712. ; (this includes the product of two digits).
  1713.  
  1714. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1715.  
  1716. ; Bignum comparison
  1717.  
  1718. (define (##bignum.= x y)
  1719.   (if (##not (##eq? (bignum-sign x) (bignum-sign y)))
  1720.     #f
  1721.     (let ((lx (bignum-length x)))
  1722.       (if (##not (##eq? lx (bignum-length y)))
  1723.         #f
  1724.         (let loop ((i (##fixnum.- lx 1)))
  1725.           (if (##fixnum.< 0 i)
  1726.             (if (##not (##eq? (bignum-digit-ref x i)
  1727.                               (bignum-digit-ref y i)))
  1728.               #f
  1729.               (loop (##fixnum.- i 1)))
  1730.             #t))))))
  1731.  
  1732. (define (##bignum.< x y)
  1733.   (if (##not (##eq? (bignum-sign x) (bignum-sign y)))
  1734.     (bignum-negative? x)
  1735.     (let ((lx (bignum-length x))
  1736.           (ly (bignum-length y)))
  1737.       (cond ((##fixnum.< lx ly)
  1738.              (bignum-positive? x))
  1739.             ((##fixnum.< ly lx)
  1740.              (bignum-negative? x))
  1741.             (else
  1742.              (let loop ((i (##fixnum.- lx 1)))
  1743.                (if (##fixnum.< 0 i)
  1744.                  (let ((dx (bignum-digit-ref x i))
  1745.                        (dy (bignum-digit-ref y i)))
  1746.                    (cond ((##fixnum.< dx dy) (bignum-positive? x))
  1747.                          ((##fixnum.< dy dx) (bignum-negative? x))
  1748.                          (else               (loop (##fixnum.- i 1)))))
  1749.                  #f)))))))
  1750.  
  1751. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1752.  
  1753. ; Operations on fixnums that might result in a bignum
  1754.  
  1755. (define (##bignum.+/fixnum-fixnum x y)
  1756.   (if (##fixnum.< x 0)
  1757.     (if (##fixnum.< y 0)
  1758.       (let ((r (##fixnum.+ x y)))
  1759.         (if (##fixnum.< r 0)
  1760.           r
  1761.           (##bignum.+/bignum-fixnum ##bignum.2*min-fixnum r)))
  1762.       (##fixnum.+ x y))
  1763.     (if (##fixnum.< y 0)
  1764.       (##fixnum.+ x y)
  1765.       (let ((r (##fixnum.+ x y)))
  1766.         (if (##fixnum.< r 0)
  1767.           (##bignum.-/fixnum-bignum r ##bignum.2*min-fixnum)
  1768.           r)))))
  1769.  
  1770. (define (##bignum.-/fixnum-fixnum x y)
  1771.   (if (##fixnum.< x 0)
  1772.     (if (##fixnum.< y 0)
  1773.       (##fixnum.- x y)
  1774.       (let ((r (##fixnum.- x y)))
  1775.         (if (##fixnum.< r 0)
  1776.           r
  1777.           (##bignum.+/bignum-fixnum ##bignum.2*min-fixnum r))))
  1778.     (if (##fixnum.< y 0)
  1779.       (let ((r (##fixnum.- x y)))
  1780.         (if (##fixnum.< r 0)
  1781.           (##bignum.-/fixnum-bignum r ##bignum.2*min-fixnum)
  1782.           r))
  1783.       (##fixnum.- x y))))
  1784.  
  1785. (define (##bignum.*/fixnum-fixnum x y)
  1786.   (cond ((and (##not (##fixnum.< x (minus-radix))) (##fixnum.< x (radix))
  1787.               (##fixnum.< (minus-radix) y) (##not (##fixnum.< (radix) y)))
  1788.          (##fixnum.* x y))
  1789.         ((or (##fixnum.= x 0) (##fixnum.= y 0))
  1790.          0)
  1791.         ((##fixnum.= x 1)
  1792.          y)
  1793.         ((##fixnum.= y 1)
  1794.          x)
  1795.         (else
  1796.          (##bignum.* (##bignum.<-fixnum x) (##bignum.<-fixnum y)))))
  1797.  
  1798. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1799.  
  1800. ; Mixed representation operations
  1801.  
  1802. (define (##bignum.+/bignum-fixnum x y)
  1803.   (##bignum.+ x (##bignum.<-fixnum y)))
  1804.  
  1805. (define (##bignum.-/bignum-fixnum x y)
  1806.   (##bignum.- x (##bignum.<-fixnum y)))
  1807.  
  1808. (define (##bignum.-/fixnum-bignum x y)
  1809.   (##bignum.- (##bignum.<-fixnum x) y))
  1810.  
  1811. (define (##bignum.*/bignum-fixnum x y)
  1812.   (cond ((##fixnum.= y 0)
  1813.          0)
  1814.         ((##fixnum.= y 1)
  1815.          x)
  1816.         (else
  1817.          (##bignum.* x (##bignum.<-fixnum y)))))
  1818.  
  1819. (define (##bignum.quotient/bignum-fixnum x y)
  1820.   (##bignum.quotient x (##bignum.<-fixnum y)))
  1821.  
  1822. (define (##bignum.quotient/fixnum-bignum x y)
  1823.   (##bignum.quotient (##bignum.<-fixnum x) y))
  1824.  
  1825. (define (##bignum.remainder/bignum-fixnum x y)
  1826.   (##bignum.remainder x (##bignum.<-fixnum y)))
  1827.  
  1828. (define (##bignum.remainder/fixnum-bignum x y)
  1829.   (##bignum.remainder (##bignum.<-fixnum x) y))
  1830.  
  1831. (define (##bignum.modulo/bignum-fixnum x y)
  1832.   (##bignum.modulo x (##bignum.<-fixnum y)))
  1833.  
  1834. (define (##bignum.modulo/fixnum-bignum x y)
  1835.   (##bignum.modulo (##bignum.<-fixnum x) y))
  1836.  
  1837. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1838.  
  1839. ; Operations where arguments are in bignum format
  1840.  
  1841. ; Addition and substraction
  1842.  
  1843. (define (##bignum.+ x y)
  1844.   (##bignum.normalize (##bignum.sum x y (bignum-sign x) (bignum-sign y))))
  1845.  
  1846. (define (##bignum.- x y)
  1847.   (##bignum.normalize (##bignum.sum x y (bignum-sign x) (bignum-sign* y))))
  1848.  
  1849. (define (##bignum.sum x y sign-x sign-y)
  1850.  
  1851.   (define (adjust-sign! x s)
  1852.     (if (##eq? (bignum-sign x) s)
  1853.       (bignum-set-positive! x)
  1854.       (bignum-set-negative! x))
  1855.     x)
  1856.  
  1857.   (cond ((##eq? sign-x sign-y) ; same sign
  1858.          (adjust-sign! (##bignum.add x y) sign-x))
  1859.         ((##fixnum.< (bignum-length x) (bignum-length y))
  1860.          (adjust-sign! (##bignum.sub y x) sign-y))
  1861.         (else
  1862.          (adjust-sign! (##bignum.sub x y) sign-x))))
  1863.  
  1864. (define (##bignum.add x y)
  1865.  
  1866.   (define (add x y lx ly)
  1867.     (let ((r (bignum-make (##fixnum.+ lx 1))))
  1868.  
  1869.       (bignum-set-positive! r)
  1870.  
  1871.       (let loop1 ((i 1) (c 0)) ; add digits in y
  1872.         (if (##fixnum.< i ly)
  1873.  
  1874.           (let ((w (##fixnum.+ (##fixnum.+ (bignum-digit-ref x i)
  1875.                                            (bignum-digit-ref y i))
  1876.                                c)))
  1877.             (if (##fixnum.< w (radix))
  1878.               (begin
  1879.                 (bignum-digit-set! r i w)
  1880.                 (loop1 (##fixnum.+ i 1) 0))
  1881.               (begin
  1882.                 (bignum-digit-set! r i (##fixnum.- w (radix)))
  1883.                 (loop1 (##fixnum.+ i 1) 1))))
  1884.  
  1885.           (let loop2 ((i i) (c c)) ; propagate carry
  1886.             (if (##fixnum.< i lx)
  1887.  
  1888.               (let ((w (##fixnum.+ (bignum-digit-ref x i) c)))
  1889.                 (if (##fixnum.< w (radix))
  1890.                   (begin
  1891.                     (bignum-digit-set! r i w)
  1892.                     (loop2 (##fixnum.+ i 1) 0))
  1893.                   (begin
  1894.                     (bignum-digit-set! r i (##fixnum.- w (radix)))
  1895.                     (loop2 (##fixnum.+ i 1) 1))))
  1896.  
  1897.               (if (##eq? c 0)
  1898.                 (bignum-shrink! r lx)
  1899.                 (bignum-digit-set! r lx c))))))
  1900.  
  1901.       r))
  1902.  
  1903.   (let ((lx (bignum-length x))
  1904.         (ly (bignum-length y)))
  1905.     (if (##fixnum.< lx ly)
  1906.       (add y x ly lx)
  1907.       (add x y lx ly))))
  1908.  
  1909. (define (##bignum.sub x y)
  1910.  
  1911.   (define (complement! r)
  1912.     (let ((lr (bignum-length r)))
  1913.       (let loop ((i 1) (c 0))
  1914.         (if (##fixnum.< i lr)
  1915.  
  1916.           (let ((w (##fixnum.+ (bignum-digit-ref r i) c)))
  1917.             (if (##fixnum.< 0 w)
  1918.               (begin
  1919.                 (bignum-digit-set! r i (##fixnum.- (radix) w))
  1920.                 (loop (##fixnum.+ i 1) 1))
  1921.               (begin
  1922.                 (bignum-digit-set! r i 0)
  1923.                 (loop (##fixnum.+ i 1) 0))))))))
  1924.  
  1925.   (define (sub x y lx ly)
  1926.     (let ((r (bignum-make lx)))
  1927.  
  1928.       (let loop1 ((i 1) (b 0)) ; substract digits in y
  1929.         (if (##fixnum.< i ly)
  1930.  
  1931.           (let ((w (##fixnum.- (##fixnum.- (bignum-digit-ref x i)
  1932.                                            (bignum-digit-ref y i))
  1933.                                b)))
  1934.             (if (##fixnum.< w 0)
  1935.               (begin
  1936.                 (bignum-digit-set! r i (##fixnum.+ w (radix)))
  1937.                 (loop1 (##fixnum.+ i 1) 1))
  1938.               (begin
  1939.                 (bignum-digit-set! r i w)
  1940.                 (loop1 (##fixnum.+ i 1) 0))))
  1941.  
  1942.           (let loop2 ((i i) (b b)) ; propagate borrow
  1943.             (if (##fixnum.< i lx)
  1944.  
  1945.               (let ((w (##fixnum.- (bignum-digit-ref x i) b)))
  1946.                 (if (##fixnum.< w 0)
  1947.                   (begin
  1948.                     (bignum-digit-set! r i (##fixnum.+ w (radix)))
  1949.                     (loop2 (##fixnum.+ i 1) 1))
  1950.                   (begin
  1951.                     (bignum-digit-set! r i w)
  1952.                     (loop2 (##fixnum.+ i 1) 0))))
  1953.  
  1954.               (if (##eq? b 0)
  1955.                 (bignum-set-positive! r)
  1956.                 (begin
  1957.                   (bignum-set-negative! r)
  1958.                   (complement! r)))))))
  1959.  
  1960.       (##bignum.remove-leading-0s! r)
  1961.  
  1962.       r))
  1963.     
  1964.   (sub x y (bignum-length x) (bignum-length y)))
  1965.  
  1966. ; Multiplication
  1967.  
  1968. (define (##bignum.* x y)
  1969.  
  1970.   (define (mul x y lx ly)
  1971.     (let ((r (bignum-make (##fixnum.- (##fixnum.+ lx ly) 1))))
  1972.  
  1973.       (if (##eq? (bignum-sign x) (bignum-sign y))
  1974.         (bignum-set-positive! r)
  1975.         (bignum-set-negative! r))
  1976.  
  1977.       (let loop1 ((j 1)) ; for each digit in y
  1978.         (if (##fixnum.< j ly)
  1979.  
  1980.           (let ((d (bignum-digit-ref y j)))
  1981.             (let loop2 ((i 1) (k j) (c 0)) ; multiply and add
  1982.               (if (##fixnum.< i lx)
  1983.  
  1984.                 (let ((w (##fixnum.+ (##fixnum.+ (bignum-digit-ref r k) c)
  1985.                                      (##fixnum.* (bignum-digit-ref x i) d))))
  1986.                   (bignum-digit-set! r k (##fixnum.modulo w (radix)))
  1987.                   (loop2 (##fixnum.+ i 1)
  1988.                          (##fixnum.+ k 1)
  1989.                          (##fixnum.quotient w (radix))))
  1990.  
  1991.                 (begin
  1992.                   (bignum-digit-set! r k c)
  1993.                   (loop1 (##fixnum.+ j 1))))))))
  1994.  
  1995.       (##bignum.remove-leading-0s! r)
  1996.  
  1997.       r))
  1998.  
  1999.   (##bignum.normalize (mul x y (bignum-length x) (bignum-length y))))
  2000.  
  2001. ; Division
  2002.  
  2003. (define (##bignum.quotient x y)
  2004.   (##bignum.normalize (##car (##bignum.div x y))))
  2005.  
  2006. (define (##bignum.remainder x y)
  2007.   (##bignum.normalize (##cdr (##bignum.div x y))))
  2008.  
  2009. (define (##bignum.modulo x y)
  2010.   (let ((r (##cdr (##bignum.div x y))))
  2011.     (if (bignum-zero? r)
  2012.       0
  2013.       (if (bignum-negative? x)
  2014.         (if (bignum-negative? y) (##bignum.normalize r) (##bignum.+ r y))
  2015.         (if (bignum-negative? y) (##bignum.+ r y) (##bignum.normalize r))))))
  2016.  
  2017. (define (##bignum.div x y)
  2018.  
  2019.   (define (single-digit-divisor-div x y lx ly r)
  2020.  
  2021.     ; simple algo for single digit divisor
  2022.  
  2023.     (let ((d (bignum-digit-ref y 1)))
  2024.       (let loop1 ((i (##fixnum.- lx 1)) (k 0))
  2025.         (if (##fixnum.< 0 i)
  2026.           (let ((w (##fixnum.+ (##fixnum.* k (radix)) (bignum-digit-ref x i))))
  2027.             (bignum-digit-set! r i (##fixnum.quotient w d))
  2028.             (loop1 (##fixnum.- i 1) (##fixnum.remainder w d)))
  2029.           (begin
  2030.             (##bignum.remove-leading-0s! r)
  2031.             (##cons r (##bignum.<-fixnum
  2032.                         (if (bignum-negative? x) (##fixnum.- 0 k) k))))))))
  2033.  
  2034.   (define (multi-digit-divisor-div x y lx ly r)
  2035.  
  2036.     ; general algo from knuth
  2037.  
  2038.     ; STEP 1: normalize x and y
  2039.  
  2040.     (let loop2 ((shift 1)
  2041.                 (n (##fixnum.* (bignum-digit-ref y (##fixnum.- ly 1)) 2)))
  2042.       (if (##fixnum.< n (radix))
  2043.         (loop2 (##fixnum.* shift 2) (##fixnum.* n 2))
  2044.  
  2045.         (let ((nx (bignum-make (##fixnum.+ lx 1)))
  2046.               (ny (bignum-make ly)))
  2047.  
  2048.           (bignum-sign-set! nx (bignum-sign x))
  2049.  
  2050.           (let loop3 ((i 1) (c 0))
  2051.             (if (##fixnum.< i lx)
  2052.               (let ((w (##fixnum.+ (##fixnum.* (bignum-digit-ref x i) shift) c)))
  2053.                 (bignum-digit-set! nx i (##fixnum.modulo w (radix)))
  2054.                 (loop3 (##fixnum.+ i 1) (##fixnum.quotient w (radix))))
  2055.               (bignum-digit-set! nx i c)))
  2056.  
  2057.           (let loop4 ((i 1) (c 0))
  2058.             (if (##fixnum.< i ly)
  2059.               (let ((w (##fixnum.+ (##fixnum.* (bignum-digit-ref y i) shift) c)))
  2060.                 (bignum-digit-set! ny i (##fixnum.modulo w (radix)))
  2061.                 (loop4 (##fixnum.+ i 1) (##fixnum.quotient w (radix))))))
  2062.  
  2063.           (let loop5 ((i lx))
  2064.             (if (##not (##fixnum.< i ly))
  2065.  
  2066.               ; STEP 2: calculate next digit in quotient
  2067.  
  2068.               (let ((msd-of-ny
  2069.                      (bignum-digit-ref ny (##fixnum.- ly 1)))
  2070.                     (next-msd-of-ny
  2071.                      (bignum-digit-ref ny (##fixnum.- ly 2)))
  2072.                     (msd-of-nx
  2073.                      (bignum-digit-ref nx i))
  2074.                     (next-msd-of-nx
  2075.                      (bignum-digit-ref nx (##fixnum.- i 1)))
  2076.                     (next-next-msd-of-nx
  2077.                      (bignum-digit-ref nx (##fixnum.- i 2))))
  2078.  
  2079.                 (define (next-digit q u)
  2080.                   (if (##fixnum.< u (radix))
  2081.                     (let* ((temp1 (##fixnum.* q next-msd-of-ny))
  2082.                            (temp2 (##fixnum.quotient temp1 (radix))))
  2083.                       (if (or (##fixnum.< u temp2)
  2084.                               (and (##eq? temp2 u)
  2085.                                    (##fixnum.<
  2086.                                      next-next-msd-of-nx
  2087.                                      (##fixnum.remainder temp1 (radix)))))
  2088.                         (next-digit (##fixnum.- q 1) (##fixnum.+ u msd-of-ny))
  2089.                         q))
  2090.                     q))
  2091.  
  2092.                 (let ((q (if (##eq? msd-of-nx msd-of-ny)
  2093.                            (next-digit
  2094.                              (radix-minus-1)
  2095.                              (##fixnum.+ msd-of-ny next-msd-of-nx))
  2096.                            (let ((temp (##fixnum.+
  2097.                                          (##fixnum.* msd-of-nx (radix))
  2098.                                          next-msd-of-nx)))
  2099.                              (next-digit
  2100.                                (##fixnum.quotient temp msd-of-ny)
  2101.                                (##fixnum.modulo temp msd-of-ny))))))
  2102.  
  2103.                   ; STEP 3: multiply and substract
  2104.  
  2105.                   (let loop7 ((j 1)
  2106.                               (k (##fixnum.- i (##fixnum.- ly 1)))
  2107.                               (b 0))
  2108.                     (if (##fixnum.< j ly)
  2109.  
  2110.                       (let ((w (##fixnum.-
  2111.                                  (##fixnum.+ (bignum-digit-ref nx k) b)
  2112.                                  (##fixnum.* (bignum-digit-ref ny j) q))))
  2113.                         (bignum-digit-set! nx k (##fixnum.modulo w (radix)))
  2114.                         (loop7 (##fixnum.+ j 1)
  2115.                                (##fixnum.+ k 1)
  2116.                                (##fixnum.quotient (##fixnum.- w (radix-minus-1))
  2117.                                                   (radix))))
  2118.  
  2119.                       (let ((w (##fixnum.+ (bignum-digit-ref nx k) b)))
  2120.                         (bignum-digit-set! nx k (##fixnum.modulo w (radix)))
  2121.                         (if (##fixnum.< w 0)
  2122.                           (begin
  2123.                             (bignum-digit-set!
  2124.                               r
  2125.                               (##fixnum.- i (##fixnum.- ly 1))
  2126.                               (##fixnum.- q 1))
  2127.                             (let loop8 ((j 1)
  2128.                                         (k (##fixnum.- i (##fixnum.- ly 1)))
  2129.                                         (c 0))
  2130.                               (if (##fixnum.< j ly)
  2131.  
  2132.                                 (let ((w (##fixnum.+
  2133.                                            (##fixnum.+
  2134.                                              (bignum-digit-ref nx k)
  2135.                                              (bignum-digit-ref ny j))
  2136.                                            c)))
  2137.                                   (bignum-digit-set!
  2138.                                     nx
  2139.                                     k
  2140.                                     (##fixnum.modulo w (radix)))
  2141.                                   (loop8 (##fixnum.+ j 1)
  2142.                                          (##fixnum.+ k 1)
  2143.                                          (##fixnum.quotient w (radix))))
  2144.                                 (bignum-digit-set!
  2145.                                   nx
  2146.                                   k
  2147.                                   (##fixnum.modulo
  2148.                                     (##fixnum.+ (bignum-digit-ref nx k) c)
  2149.                                     (radix))))))
  2150.                             (bignum-digit-set!
  2151.                               r
  2152.                               (##fixnum.- i (##fixnum.- ly 1))
  2153.                               q))
  2154.                         (loop5 (##fixnum.- i 1)))))))))
  2155.  
  2156.           (let loop9 ((i (##fixnum.- ly 1)) (k 0))
  2157.             (if (##fixnum.< 0 i)
  2158.               (let ((w (##fixnum.+ (##fixnum.* k (radix))
  2159.                                    (bignum-digit-ref nx i))))
  2160.                 (bignum-digit-set! nx i (##fixnum.quotient w shift))
  2161.                 (loop9 (##fixnum.- i 1)
  2162.                        (##fixnum.remainder w shift)))))
  2163.  
  2164.           (##bignum.remove-leading-0s! nx)
  2165.           (##bignum.remove-leading-0s! r)
  2166.           (##cons r nx)))))
  2167.  
  2168.   (define (div x y lx ly)
  2169.     (if (##fixnum.< lx ly)
  2170.  
  2171.       (##cons ##bignum.0 x)
  2172.  
  2173.       (let ((r (bignum-make (##fixnum.+ (##fixnum.- lx ly) 2))))
  2174.  
  2175.         (if (##eq? (bignum-sign x) (bignum-sign y))
  2176.           (bignum-set-positive! r)
  2177.           (bignum-set-negative! r))
  2178.  
  2179.         (if (##eq? ly 2)
  2180.           (single-digit-divisor-div x y lx ly r)
  2181.           (multi-digit-divisor-div x y lx ly r)))))
  2182.  
  2183.   (div x y (bignum-length x) (bignum-length y)))
  2184.  
  2185. ; Conversion to string
  2186.  
  2187. (define (##bignum.number->string n rad)
  2188.  
  2189.   (define (bignum->string n rad r r-log-rad radix-log-r-num)
  2190.     (let ((len (##fixnum.* (##fixnum.quotient
  2191.                              (##fixnum.+
  2192.                                (##fixnum.* (##fixnum.- (bignum-length n) 1)
  2193.                                            radix-log-r-num)
  2194.                                (##fixnum.- (radix-log-den) 1))
  2195.                              (radix-log-den))
  2196.                            r-log-rad)))
  2197.       (let ((n (##bignum.copy n))
  2198.             (s (##make-string (##fixnum.+ len 1) #\space)))
  2199.  
  2200.         (define (put-digits k i)
  2201.           (let loop1 ((k k) (i i) (j r-log-rad) (last-non-zero i))
  2202.             (if (##fixnum.< 0 j)
  2203.               (let ((d (##fixnum.remainder k rad)))
  2204.                 (##string-set! s i
  2205.                   (##string-ref "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" d))
  2206.                 (loop1 (##fixnum.quotient k rad)
  2207.                        (##fixnum.- i 1)
  2208.                        (##fixnum.- j 1)
  2209.                        (if (##eq? d 0) last-non-zero i)))
  2210.               last-non-zero)))
  2211.  
  2212.         (define (move-digits i j)
  2213.           (let loop2 ((i i) (j j))
  2214.             (if (##fixnum.< len i)
  2215.               (##string-shrink! s j)
  2216.               (begin
  2217.                 (##string-set! s j (##string-ref s i))
  2218.                 (loop2 (##fixnum.+ i 1) (##fixnum.+ j 1))))))
  2219.  
  2220.         (let loop3 ((i len))
  2221.  
  2222.           (let ((k
  2223.                  ; k = next digit in base `r'
  2224.                  ; use simple algo for dividing in place by `r'
  2225.                  ; (which is known to be less than or equal to radix)
  2226.  
  2227.                  (let loop4 ((j (##fixnum.- (bignum-length n) 1)) (k 0))
  2228.                    (if (##fixnum.< 0 j)
  2229.                      (let ((x (##fixnum.+ (##fixnum.* k (radix))
  2230.                                           (bignum-digit-ref n j))))
  2231.                        (bignum-digit-set! n j (##fixnum.quotient x r))
  2232.                        (loop4 (##fixnum.- j 1) (##fixnum.remainder x r)))
  2233.                      k))))
  2234.  
  2235.             (let ((last-non-zero (put-digits k i)))
  2236.               (##bignum.remove-leading-0s! n)
  2237.               (if (##not (bignum-zero? n))
  2238.                 (loop3 (##fixnum.- i r-log-rad))
  2239.                 (if (bignum-negative? n)
  2240.                   (begin
  2241.                     (##string-set! s 0 #\-)
  2242.                     (move-digits last-non-zero 1))
  2243.                   (move-digits last-non-zero 0)))))))))
  2244.  
  2245.   (cond ((##eq? rad 2)
  2246.          (bignum->string n rad (r.2) (r-log-rad.2) (radix-log-r-num.2)))
  2247.         ((##eq? rad 8)
  2248.          (bignum->string n rad (r.8) (r-log-rad.8) (radix-log-r-num.8)))
  2249.         ((##eq? rad 10)
  2250.          (bignum->string n rad (r.10) (r-log-rad.10) (radix-log-r-num.10)))
  2251.         (else
  2252.          (bignum->string n rad (r.16) (r-log-rad.16) (radix-log-r-num.16)))))
  2253.  
  2254. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2255.  
  2256. ; Utilities:
  2257.  
  2258. (define (##bignum.copy x)
  2259.   (let ((len (bignum-length x)))
  2260.     (let ((y (bignum-make len)))
  2261.       (let loop ((i (##fixnum.- len 1)))
  2262.         (if (##fixnum.< i 0)
  2263.           y
  2264.           (begin
  2265.             (bignum-digit-set! y i (bignum-digit-ref x i))
  2266.             (loop (##fixnum.- i 1))))))))
  2267.  
  2268. (define (##bignum.remove-leading-0s! x)
  2269.   (let ((sign (bignum-sign x)))
  2270.     (bignum-sign-set! x 1) ; set to something different than 0
  2271.     (let loop ((i (##fixnum.- (bignum-length x) 1)))
  2272.       (if (##eq? (bignum-digit-ref x i) 0)
  2273.         (loop (##fixnum.- i 1))
  2274.         (bignum-shrink! x (##fixnum.+ i 1))))
  2275.     (bignum-sign-set! x sign)))
  2276.  
  2277. (define (##bignum.normalize x)
  2278.   (let ((lx-minus-1 (##fixnum.- (bignum-length x) 1)))
  2279.     (if (##fixnum.< (max-digits-for-fixnum) lx-minus-1)
  2280.       x
  2281.       (let loop ((n 0) (i lx-minus-1))
  2282.         (cond ((##fixnum.< 0 i)
  2283.                (if (##fixnum.< n (min-fixnum-div-radix))
  2284.                  x
  2285.                  (let ((y (##fixnum.- (##fixnum.* n (radix))
  2286.                                       (bignum-digit-ref x i))))
  2287.                    (if (##fixnum.< y 0)
  2288.                      (loop y (##fixnum.- i 1))
  2289.                      x))))
  2290.               ((bignum-negative? x)
  2291.                n)
  2292.               (else
  2293.                (let ((n (##fixnum.- 0 n)))
  2294.                  (if (##fixnum.< n 0) x n))))))))
  2295.  
  2296. (define (##bignum.<-fixnum n)
  2297.   (if (or (##fixnum.< n -16) (##fixnum.< 16 n))
  2298.     (##bignum.<-fixnum* n)
  2299.     (##vector-ref ##bignum.constants (##fixnum.+ n 16))))
  2300.  
  2301. (define (##bignum.<-fixnum* n)
  2302.   (let ((neg-n (if (##fixnum.< n 0) n (##fixnum.- 0 n))))
  2303.     (let loop1 ((nb-digits 0) (x neg-n))
  2304.       (if (##not (##eq? x 0))
  2305.         (loop1 (##fixnum.+ nb-digits 1) (##fixnum.quotient x (radix)))
  2306.         (let ((r (bignum-make (##fixnum.+ nb-digits 1))))
  2307.           (if (##fixnum.< n 0)
  2308.             (bignum-set-negative! r)
  2309.             (bignum-set-positive! r))
  2310.           (let loop2 ((i 1) (x neg-n))
  2311.             (if (##not (##eq? x 0))
  2312.               (begin
  2313.                 (bignum-digit-set!
  2314.                   r
  2315.                   i
  2316.                   (##fixnum.- 0 (##fixnum.remainder x (radix))))
  2317.                 (loop2 (##fixnum.+ i 1) (##fixnum.quotient x (radix))))
  2318.               r)))))))
  2319.  
  2320. (define ##bignum.constants
  2321.   (let ((v (##make-vector 33 #f)))
  2322.     (let loop ((i 0) (n -16))
  2323.       (if (##not (##fixnum.< 16 n))
  2324.         (begin
  2325.           (##vector-set! v i (##bignum.<-fixnum* n))
  2326.           (loop (##fixnum.+ i 1) (##fixnum.+ n 1)))))
  2327.     v))
  2328.  
  2329. (define ##bignum.0
  2330.   (##bignum.<-fixnum 0))
  2331.  
  2332. (define ##bignum.2*min-fixnum
  2333.   (##bignum.* (##bignum.<-fixnum (min-fixnum)) (##bignum.<-fixnum 2)))
  2334.  
  2335. ;------------------------------------------------------------------------------
  2336.  
  2337. ; Ratnum operations
  2338. ; -----------------
  2339.  
  2340. (define (##ratnum.= x y)
  2341.   (and (##= (ratnum-numerator x) (ratnum-numerator y))
  2342.        (##= (ratnum-denominator x) (ratnum-denominator y))))
  2343.  
  2344. (define (##ratnum.< x y)
  2345.   (##< (##* (ratnum-numerator x) (ratnum-denominator y))
  2346.        (##* (ratnum-denominator x) (ratnum-numerator y))))
  2347.  
  2348. (define (##ratnum.+ x y)
  2349.   (##ratnum.normalize
  2350.     (##+ (##* (ratnum-numerator x) (ratnum-denominator y))
  2351.          (##* (ratnum-denominator x) (ratnum-numerator y)))
  2352.     (##* (ratnum-denominator x) (ratnum-denominator y))))
  2353.  
  2354. (define (##ratnum.* x y)
  2355.   (##ratnum.normalize
  2356.     (##* (ratnum-numerator x) (ratnum-numerator y))
  2357.     (##* (ratnum-denominator x) (ratnum-denominator y))))
  2358.  
  2359. (define (##ratnum.- x y)
  2360.   (##ratnum.normalize
  2361.     (##- (##* (ratnum-numerator x) (ratnum-denominator y))
  2362.          (##* (ratnum-denominator x) (ratnum-numerator y)))
  2363.     (##* (ratnum-denominator x) (ratnum-denominator y))))
  2364.  
  2365. (define (##ratnum./ x y)
  2366.   (##ratnum.normalize
  2367.     (##* (ratnum-numerator x) (ratnum-denominator y))
  2368.     (##* (ratnum-denominator x) (ratnum-numerator y))))
  2369.  
  2370. (define (##ratnum.floor x)
  2371.   (let ((num (ratnum-numerator x))
  2372.         (den (ratnum-denominator x)))
  2373.     (if (##negative? num)
  2374.       (##quotient (##- num (##- den 1)) den)
  2375.       (##quotient num den))))
  2376.  
  2377. (define (##ratnum.ceiling x)
  2378.   (let ((num (ratnum-numerator x))
  2379.         (den (ratnum-denominator x)))
  2380.     (if (##negative? num)
  2381.       (##quotient num den)
  2382.       (##quotient (##+ num (##- den 1)) den))))
  2383.  
  2384. (define (##ratnum.truncate x)
  2385.   (##quotient (ratnum-numerator x) (ratnum-denominator x)))
  2386.  
  2387. (define (##ratnum.round x)
  2388.   (let ((num (ratnum-numerator x))
  2389.         (den (ratnum-denominator x)))
  2390.     (if (##eq? den 2)
  2391.       (if (##negative? num)
  2392.         (##* (##quotient (##- num 1) 4) 2)
  2393.         (##* (##quotient (##+ num 1) 4) 2))
  2394.       (##floor (##ratnum.normalize (##+ (##* num 2) den) (##* den 2))))))
  2395.  
  2396. (define (##ratnum.normalize num den)
  2397.   (let ((x (##gcd num den)))
  2398.     (let ((y (if (##negative? den) (##- 0 x) x)))
  2399.       (let ((num (##quotient num y))
  2400.             (den (##quotient den y)))
  2401.         (if (##eq? den 1)
  2402.           num
  2403.           (ratnum-make num den))))))
  2404.  
  2405. (define (##ratnum.<-exact-int x)
  2406.   (ratnum-make x 1))
  2407.  
  2408. ;------------------------------------------------------------------------------
  2409.  
  2410. ; Flonum operations
  2411. ; -----------------
  2412.  
  2413. (define-system (##flonum.->fixnum x))
  2414.  
  2415. (define-system (##flonum.<-fixnum x))
  2416.  
  2417. (define-nary0 (##flonum.+ x y) (inexact-0) x (##flonum.+ x y) no-touch)
  2418. (define-nary0 (##flonum.* x y) (inexact-+1) x (##flonum.* x y) no-touch)
  2419. (define-nary1 (##flonum.- x y) (##flonum.- (inexact-0) x) (##flonum.- x y) no-touch)
  2420. (define-nary1 (##flonum./ x y) (##flonum./ (inexact-+1) x) (##flonum./ x y) no-touch)
  2421.  
  2422. (define-system (##flonum.abs x))
  2423.  
  2424. (define-system (##flonum.floor x)
  2425.   (let ((y (##flonum.truncate x)))
  2426.     (if (or (##flonum.= x y) (##flonum.positive? x))
  2427.       y
  2428.       (##flonum.- y (inexact-+1)))))
  2429.  
  2430. (define-system (##flonum.ceiling x)
  2431.   (let ((y (##flonum.truncate x)))
  2432.     (if (or (##flonum.= x y) (##flonum.negative? x))
  2433.       y
  2434.       (##flonum.+ y (inexact-+1)))))
  2435.  
  2436. (define-system (##flonum.truncate x))
  2437. (define-system (##flonum.round x))
  2438.  
  2439. (define-system (##flonum.exp x))
  2440. (define-system (##flonum.log x))
  2441. (define-system (##flonum.sin x))
  2442. (define-system (##flonum.cos x))
  2443. (define-system (##flonum.tan x))
  2444. (define-system (##flonum.asin x))
  2445. (define-system (##flonum.acos x))
  2446. (define-system (##flonum.atan x))
  2447. (define-system (##flonum.sqrt x))
  2448.  
  2449. (define-system (##flonum.zero? x)
  2450.   (##flonum.= x (inexact-0)))
  2451.  
  2452. (define-system (##flonum.positive? x)
  2453.   (##flonum.< (inexact-0) x))
  2454.  
  2455. (define-system (##flonum.negative? x)
  2456.   (##flonum.< x (inexact-0)))
  2457.  
  2458. (define-nary0-boolean (##flonum.= x y)
  2459.   (##flonum.= x y) no-check no-touch)
  2460.  
  2461. (define-nary0-boolean (##flonum.< x y)
  2462.   (##flonum.< x y) no-check no-touch)
  2463.  
  2464. (define-nary0-boolean (##flonum.> x y)
  2465.   (##flonum.< y x) no-check no-touch)
  2466.  
  2467. (define-nary0-boolean (##flonum.<= x y)
  2468.   (##not (##flonum.< y x)) no-check no-touch)
  2469.  
  2470. (define-nary0-boolean (##flonum.>= x y)
  2471.   (##not (##flonum.< x y)) no-check no-touch)
  2472.  
  2473. (define (##flonum.<-ratnum x)
  2474.   (##flonum./ (##exact->inexact (ratnum-numerator x))
  2475.               (##exact->inexact (ratnum-denominator x))))
  2476.  
  2477. (define (##flonum.<-bignum x)
  2478.   (let ((lx (bignum-length x)))
  2479.     (let loop ((i (##fixnum.- lx 1)) (res (inexact-0)))
  2480.       (if (##fixnum.< 0 i)
  2481.         (loop (##fixnum.- i 1)
  2482.               (##flonum.+ (##flonum.* res (inexact-radix))
  2483.                           (##flonum.<-fixnum (bignum-digit-ref x i))))
  2484.         (if (bignum-negative? x)
  2485.           (##flonum.- (inexact-0) res)
  2486.           res)))))
  2487.  
  2488. (define (##flonum.->exact-int x)
  2489.   (let loop1 ((z (##flonum.abs x)) (n 1))
  2490.     (if (##flonum.< (inexact-radix) z)
  2491.       (loop1 (##flonum./ z (inexact-radix)) (##fixnum.+ n 1))
  2492.       (let loop2 ((res 0) (z z) (n n))
  2493.         (if (##fixnum.< 0 n)
  2494.           (let ((truncated-z (##flonum.truncate z)))
  2495.             (loop2 (##+ (##flonum.->fixnum truncated-z) (##* res (radix)))
  2496.                    (##flonum.* (##flonum.- z truncated-z) (inexact-radix))
  2497.                    (##fixnum.- n 1)))
  2498.           (if (##flonum.negative? x)
  2499.             (##- 0 res)
  2500.             res))))))
  2501.  
  2502. (define (##flonum.->inexact-exponential-format x)
  2503.  
  2504.   (define (exp-form-pos x y i)
  2505.     (let ((i*2 (##fixnum.+ i i)))
  2506.       (let ((z (if (and (##not (##fixnum.< (flonum-e-bias) i*2))
  2507.                         (##not (##flonum.< x y)))
  2508.                  (exp-form-pos x (##flonum.* y y) i*2)
  2509.                  (##cons x 0))))
  2510.         (let ((a (##car z)) (b (##cdr z)))
  2511.           (let ((i+b (##fixnum.+ i b)))
  2512.             (if (and (##not (##fixnum.< (flonum-e-bias) i+b))
  2513.                      (##not (##flonum.< a y)))
  2514.               (begin
  2515.                 (##set-car! z (##flonum./ a y))
  2516.                 (##set-cdr! z i+b)))
  2517.             z)))))
  2518.  
  2519.   (define (exp-form-neg x y i)
  2520.     (let ((i*2 (##fixnum.+ i i)))
  2521.       (let ((z (if (and (##fixnum.< i*2 (flonum-e-bias-minus-1))
  2522.                         (##flonum.< x y))
  2523.                  (exp-form-neg x (##flonum.* y y) i*2)
  2524.                  (##cons x 0))))
  2525.         (let ((a (##car z)) (b (##cdr z)))
  2526.           (let ((i+b (##fixnum.+ i b)))
  2527.             (if (and (##fixnum.< i+b (flonum-e-bias-minus-1))
  2528.                      (##flonum.< a y))
  2529.               (begin
  2530.                 (##set-car! z (##flonum./ a y))
  2531.                 (##set-cdr! z i+b)))
  2532.             z)))))
  2533.  
  2534.   (define (exp-form x)
  2535.     (if (##flonum.< x (inexact-+1))
  2536.       (let ((z (exp-form-neg x (inexact-+1/2) 1)))
  2537.         (##set-car! z (##flonum.* (inexact-+2) (##car z)))
  2538.         (##set-cdr! z (##fixnum.- -1 (##cdr z)))
  2539.         z)
  2540.       (exp-form-pos x (inexact-+2) 1)))
  2541.  
  2542.   (if (##flonum.negative? x)
  2543.     (let ((z (exp-form (##flonum.abs x))))
  2544.       (##set-car! z (##flonum.- (inexact-0) (##car z)))
  2545.       z)
  2546.     (exp-form x)))
  2547.  
  2548. (define (##flonum.->exact-exponential-format x)
  2549.   (let ((z (##flonum.->inexact-exponential-format x)))
  2550.     (let ((y (##car z)))
  2551.       (cond ((##not (##flonum.< y (inexact-+2)))
  2552.              (##set-car! z (flonum-+m-min))
  2553.              (##set-cdr! z (flonum-e-bias-plus-1)))
  2554.             ((##not (##flonum.< (inexact--2) y))
  2555.              (##set-car! z (flonum--m-min))
  2556.              (##set-cdr! z (flonum-e-bias-plus-1)))
  2557.             (else
  2558.              (##set-car! z (##flonum.->exact-int (##flonum.* (##car z) (flonum-m-min))))))
  2559.       (##set-cdr! z (##fixnum.- (##cdr z) (flonum-m-bits)))
  2560.       z)))
  2561.  
  2562. (define (##flonum.inexact->exact x)
  2563.   (let ((z (##flonum.->exact-exponential-format x)))
  2564.     (##* (##car z) (##expt 2 (##cdr z)))))
  2565.  
  2566. (define (##flonum.->bits x)
  2567.  
  2568.   (define (bits a b)
  2569.     (if (##< a (flonum-+m-min))
  2570.       a
  2571.       (##+ (##- a (flonum-+m-min))
  2572.            (##* (##fixnum.+ (##fixnum.+ b (flonum-m-bits)) (flonum-e-bias))
  2573.                 (flonum-+m-min)))))
  2574.  
  2575.   (let ((z (##flonum.->exact-exponential-format x)))
  2576.     (let ((a (##car z)) (b (##cdr z)))
  2577.       (if (##negative? a)
  2578.         (##+ (flonum-sign-bit) (bits (##- 0 a) b))
  2579.         (bits a b)))))
  2580.  
  2581. (define (##flonum.->ratnum x)
  2582.   (let ((y (##flonum.inexact->exact x)))
  2583.     (if (exact-int? y)
  2584.       (##ratnum.<-exact-int y)
  2585.       y)))
  2586.  
  2587. ;------------------------------------------------------------------------------
  2588.  
  2589. ; Cpxnum operations
  2590. ; -----------------
  2591.  
  2592. (define (##cpxnum.= x y)
  2593.   (and (##= (cpxnum-real x) (cpxnum-real y))
  2594.        (##= (cpxnum-imag x) (cpxnum-imag y))))
  2595.  
  2596. (define (##cpxnum.+ x y)
  2597.   (let ((a (cpxnum-real x)) (b (cpxnum-imag x))
  2598.         (c (cpxnum-real y)) (d (cpxnum-imag y)))
  2599.     (##make-rectangular (##+ a c) (##+ b d))))
  2600.  
  2601. (define (##cpxnum.* x y)
  2602.   (let ((a (cpxnum-real x)) (b (cpxnum-imag x))
  2603.         (c (cpxnum-real y)) (d (cpxnum-imag y)))
  2604.     (##make-rectangular (##- (##* a c) (##* b d)) (##+ (##* a d) (##* b c)))))
  2605.  
  2606. (define (##cpxnum.- x y)
  2607.   (let ((a (cpxnum-real x)) (b (cpxnum-imag x))
  2608.         (c (cpxnum-real y)) (d (cpxnum-imag y)))
  2609.     (##make-rectangular (##- a c) (##- b d))))
  2610.  
  2611. (define (##cpxnum./ x y)
  2612.   (let ((a (cpxnum-real x)) (b (cpxnum-imag x))
  2613.         (c (cpxnum-real y)) (d (cpxnum-imag y)))
  2614.     (let ((q (##+ (##* c c) (##* d d))))
  2615.       (##make-rectangular (##/ (##+ (##* a c) (##* b d)) q)
  2616.                           (##/ (##- (##* b c) (##* a d)) q)))))
  2617.  
  2618. (define (##cpxnum.<-non-cpxnum x)
  2619.   (cpxnum-make x 0))
  2620.  
  2621. ;------------------------------------------------------------------------------
  2622.